mirror of
https://github.com/github/codeql.git
synced 2026-06-19 11:51:08 +02:00
Merge branch 'main' into felickz/razor-page-handler-sources
This commit is contained in:
@@ -59,9 +59,5 @@ MODULE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/rust.yml @github/codeql-rust
|
||||
/.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/ @github/codeql-ci-reviewers
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -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`.
|
||||
@@ -50,15 +50,15 @@ private predicate maybeUsedInElfHashFunction(Variable v, Operation xor, Operatio
|
||||
|
|
||||
add instanceof AddOperation and
|
||||
e1.getAChild*() = add.getAnOperand() and
|
||||
e1 instanceof BinaryBitwiseOperation and
|
||||
e2 = e1.(BinaryBitwiseOperation).getLeftOperand() and
|
||||
e1 instanceof BinaryBitwiseExpr and
|
||||
e2 = e1.(BinaryBitwiseExpr).getLeftOperand() and
|
||||
v = addAssign.getTargetVariable() and
|
||||
addAssign.getAChild*() = add and
|
||||
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
|
||||
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
|
||||
xorAssign.getAChild*() = xor 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
|
||||
notAssign.getAChild*() = notOp and
|
||||
v = notAssign.getTargetVariable() and
|
||||
|
||||
@@ -290,7 +290,7 @@ module AssignableInternal {
|
||||
newtype TAssignableDefinition =
|
||||
TAssignmentDefinition(Assignment a) {
|
||||
not a.getLeftOperand() instanceof TupleExpr and
|
||||
not a instanceof AssignCallOperation and
|
||||
not a instanceof AssignCallExpr and
|
||||
not a instanceof AssignCoalesceExpr
|
||||
} or
|
||||
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
|
||||
@@ -324,7 +324,7 @@ module AssignableInternal {
|
||||
TAddressOfDefinition(AddressOfExpr aoe) or
|
||||
TPatternDefinition(TopLevelPatternDecl tlpd) or
|
||||
TAssignOperationDefinition(AssignOperation ao) {
|
||||
ao instanceof AssignCallOperation and not ao instanceof CompoundAssignmentOperatorCall
|
||||
ao instanceof AssignCallExpr and not ao instanceof CompoundAssignmentOperatorCall
|
||||
or
|
||||
ao instanceof AssignCoalesceExpr
|
||||
}
|
||||
|
||||
@@ -912,18 +912,17 @@ module Internal {
|
||||
)
|
||||
or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
exists(BinaryOperation bo, Expr o |
|
||||
bo instanceof BinaryArithmeticOperation or
|
||||
bo instanceof AssignArithmeticOperation
|
||||
|
|
||||
result = bo and
|
||||
bo.getAnOperand() = e and
|
||||
bo.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
result =
|
||||
any(BinaryArithmeticOperation bao |
|
||||
exists(Expr o |
|
||||
bao.getAnOperand() = e and
|
||||
bao.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
nonNullValueImplied(o) and
|
||||
e != o
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -934,10 +933,10 @@ module Internal {
|
||||
any(QualifiableExpr qe |
|
||||
qe.isConditional() and
|
||||
result = qe.getQualifier()
|
||||
) or
|
||||
)
|
||||
or
|
||||
// In C#, `null + 1` has type `int?` with value `null`
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) or
|
||||
e = any(AssignArithmeticOperation aao | result = aao.getAnOperand())
|
||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand())
|
||||
}
|
||||
|
||||
deprecated predicate isGuard(Expr e, GuardValue val) {
|
||||
|
||||
@@ -172,6 +172,10 @@ module Ast implements AstSig<Location> {
|
||||
|
||||
class DoStmt = CS::DoStmt;
|
||||
|
||||
class UntilStmt extends LoopStmt {
|
||||
UntilStmt() { none() }
|
||||
}
|
||||
|
||||
final private class FinalForStmt = CS::ForStmt;
|
||||
|
||||
class ForStmt extends FinalForStmt {
|
||||
|
||||
@@ -124,9 +124,7 @@ private module Internal {
|
||||
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
|
||||
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
|
||||
TDispatchDynamicElementAccess(DynamicElementAccess dea) or
|
||||
TDispatchDynamicEventAccess(
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
TDispatchDynamicEventAccess(AssignArithmeticExpr aao, DynamicMemberAccess dma, string name) {
|
||||
isPotentialEventCall(aao, dma, name)
|
||||
} or
|
||||
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
|
||||
@@ -230,7 +228,7 @@ private module Internal {
|
||||
* accessor.
|
||||
*/
|
||||
private predicate isPotentialEventCall(
|
||||
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||
AssignArithmeticExpr aao, DynamicMemberAccess dma, string name
|
||||
) {
|
||||
aao instanceof DynamicOperatorCall and
|
||||
dma = aao.getLeftOperand() and
|
||||
@@ -1397,9 +1395,7 @@ private module Internal {
|
||||
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
|
||||
TDispatchDynamicEventAccess
|
||||
{
|
||||
override AssignArithmeticOperation getCall() {
|
||||
this = TDispatchDynamicEventAccess(result, _, _)
|
||||
}
|
||||
override AssignArithmeticExpr getCall() { this = TDispatchDynamicEventAccess(result, _, _) }
|
||||
|
||||
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }
|
||||
|
||||
|
||||
@@ -11,19 +11,27 @@ import Expr
|
||||
* (`UnaryArithmeticOperation`) or a binary arithmetic operation
|
||||
* (`BinaryArithmeticOperation`).
|
||||
*/
|
||||
class ArithmeticOperation extends Operation, @arith_op_expr {
|
||||
class ArithmeticOperation extends Operation, @arith_operation {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A unary arithmetic operation. Either a unary minus operation
|
||||
* (`UnaryMinusExpr`), a unary plus operation (`UnaryPlusExpr`),
|
||||
* or a mutator operation (`MutatorOperation`).
|
||||
* A binary arithmetic operation. Either a binary arithmetic expression (`BinaryArithmeticExpr`) or
|
||||
* an arithmetic assignment expression (`AssignArithmeticExpr`).
|
||||
*/
|
||||
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 {
|
||||
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 {
|
||||
override string getOperator() { result = "+" }
|
||||
@@ -44,40 +52,40 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||
* A mutator operation. Either an increment operation (`IncrementOperation`)
|
||||
* 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
|
||||
* (`PostIncrExpr`) or a prefix increment operation (`PreIncrExpr`).
|
||||
* An increment operation. Either a postfix increment expression
|
||||
* (`PostIncrExpr`) or a prefix increment expression (`PreIncrExpr`).
|
||||
*/
|
||||
class IncrementOperation extends MutatorOperation, @incr_op_expr {
|
||||
class IncrementOperation extends MutatorOperation, @incr_operation {
|
||||
override string getOperator() { result = "++" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A decrement operation. Either a postfix decrement operation
|
||||
* (`PostDecrExpr`) or a prefix decrement operation (`PreDecrExpr`).
|
||||
* A decrement operation. Either a postfix decrement expression
|
||||
* (`PostDecrExpr`) or a prefix decrement expression (`PreDecrExpr`).
|
||||
*/
|
||||
class DecrementOperation extends MutatorOperation, @decr_op_expr {
|
||||
class DecrementOperation extends MutatorOperation, @decr_operation {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
* (`AddExpr`), a subtraction operation (`SubExpr`), a multiplication
|
||||
* operation (`MulExpr`), a division operation (`DivExpr`), or a
|
||||
* remainder operation (`RemExpr`).
|
||||
* An addition operation, either `x + y` or `x += y`.
|
||||
*/
|
||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_op_expr {
|
||||
override string getOperator() { none() }
|
||||
class AddOperation extends BinaryArithmeticOperation, @add_operation { }
|
||||
|
||||
/**
|
||||
* 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 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 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 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 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 getAPrimaryQlClass() { result = "RemExpr" }
|
||||
|
||||
@@ -72,9 +72,9 @@ class AssignExpr extends Assignment, @simple_assign_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* An assignment operation. Either an arithmetic assignment operation
|
||||
* (`AssignArithmeticOperation`), a bitwise assignment operation
|
||||
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* An assignment operation. Either an arithmetic assignment expression
|
||||
* (`AssignArithmeticExpr`), a bitwise assignment expression
|
||||
* (`AssignBitwiseExpr`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||
* a null-coalescing assignment (`AssignCoalesceExpr`).
|
||||
*/
|
||||
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).
|
||||
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
|
||||
*
|
||||
* Either an arithmetic assignment operation (`AssignArithmeticOperation`) or a bitwise
|
||||
* assignment operation (`AssignBitwiseOperation`).
|
||||
* Either an arithmetic assignment expression (`AssignArithmeticExpr`) or a bitwise
|
||||
* assignment expression (`AssignBitwiseExpr`).
|
||||
*/
|
||||
class AssignCallOperation extends AssignOperation, OperatorCall, QualifiableExpr,
|
||||
@assign_op_call_expr
|
||||
{
|
||||
class AssignCallExpr extends AssignOperation, OperatorCall, QualifiableExpr, @assign_op_call_expr {
|
||||
override string toString() { result = AssignOperation.super.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An arithmetic assignment operation. Either an addition assignment operation
|
||||
* (`AssignAddExpr`), a subtraction assignment operation (`AssignSubExpr`), a
|
||||
* multiplication assignment operation (`AssignMulExpr`), a division assignment
|
||||
* operation (`AssignDivExpr`), or a remainder assignment operation
|
||||
* (`AssignRemExpr`).
|
||||
* DEPRECATED: Use `AssignCallExpr` instead.
|
||||
*/
|
||||
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 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 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 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 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 getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise assignment operation. Either a bitwise-and assignment
|
||||
* operation (`AssignAndExpr`), a bitwise-or assignment
|
||||
* operation (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* operation (`AssignXorExpr`), a left-shift assignment
|
||||
* operation (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* operation (`AssignUnsignedRightShiftExpr`).
|
||||
* A bitwise assignment expression. Either a bitwise-and assignment
|
||||
* expression (`AssignAndExpr`), a bitwise-or assignment
|
||||
* expression (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||
* expression (`AssignXorExpr`), a left-shift assignment
|
||||
* expression (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||
* expression (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||
* 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 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 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 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 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 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
|
||||
{
|
||||
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 {
|
||||
override string toString() { result = "... ??= ..." }
|
||||
override string getOperator() { result = "??=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
|
||||
}
|
||||
|
||||
@@ -10,16 +10,16 @@ import Expr
|
||||
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
|
||||
* 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
|
||||
* (`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 {
|
||||
override string getOperator() { result = "~" }
|
||||
@@ -28,67 +28,101 @@ class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary bitwise operation. Either a bitwise-and operation
|
||||
* (`BitwiseAndExpr`), a bitwise-or operation (`BitwiseOrExpr`),
|
||||
* a bitwise exclusive-or operation (`BitwiseXorExpr`), a left-shift
|
||||
* operation (`LeftShiftExpr`), a right-shift operation (`RightShiftExpr`),
|
||||
* or an unsigned right-shift operation (`UnsignedRightShiftExpr`).
|
||||
* A binary bitwise operation. Either a binary bitwise expression (`BinaryBitwiseExpr`) or
|
||||
* a bitwise assignment expression (`AssignBitwiseExpr`).
|
||||
*/
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_op_expr {
|
||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_operation {
|
||||
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 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 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,
|
||||
@urshift_expr
|
||||
{
|
||||
class UnsignedRightShiftExpr extends BinaryBitwiseExpr, UnsignedRightShiftOperation, @urshift_expr {
|
||||
override string getOperator() { result = ">>>" }
|
||||
|
||||
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 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 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 getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
|
||||
@@ -609,7 +609,7 @@ class InstanceMutatorOperatorCall extends MutatorOperatorCall {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CompoundAssignmentOperatorCall extends AssignCallOperation {
|
||||
class CompoundAssignmentOperatorCall extends AssignCallExpr {
|
||||
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
|
||||
|
||||
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }
|
||||
|
||||
@@ -14,7 +14,6 @@ import Creation
|
||||
import Dynamic
|
||||
import Literal
|
||||
import LogicalOperation
|
||||
import Operation
|
||||
import semmle.code.csharp.controlflow.ControlFlowElement
|
||||
import semmle.code.csharp.Location
|
||||
import semmle.code.csharp.Stmt
|
||||
@@ -212,7 +211,7 @@ class LocalConstantDeclExpr extends LocalVariableDeclExpr {
|
||||
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
|
||||
* ternary operation (`TernaryOperation`).
|
||||
*/
|
||||
class Operation extends Expr, @op_expr {
|
||||
class Operation extends Expr, @operation_expr {
|
||||
/** Gets the name of the operator in this operation. */
|
||||
string getOperator() { none() }
|
||||
|
||||
@@ -227,7 +226,7 @@ class Operation extends Expr, @op_expr {
|
||||
* indirection operation (`PointerIndirectionExpr`), an address-of operation
|
||||
* (`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. */
|
||||
Expr getOperand() { result = this.getChild(0) }
|
||||
|
||||
@@ -241,7 +240,7 @@ class UnaryOperation extends Operation, @un_op {
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or an
|
||||
* assignment (`Assignment`).
|
||||
*/
|
||||
class BinaryOperation extends Operation, @bin_op {
|
||||
class BinaryOperation extends Operation, @bin_operation {
|
||||
/** Gets the left operand of this binary operation. */
|
||||
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
|
||||
* (`ConditionalExpr`).
|
||||
*/
|
||||
class TernaryOperation extends Operation, @ternary_op { }
|
||||
class TernaryOperation extends Operation, @ternary_operation { }
|
||||
|
||||
/**
|
||||
* A parenthesized expression, for example `(2 + 3)` in
|
||||
|
||||
@@ -11,14 +11,14 @@ import Expr
|
||||
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
|
||||
* operation (`TernaryLogicalOperation`).
|
||||
*/
|
||||
class LogicalOperation extends Operation, @log_expr {
|
||||
class LogicalOperation extends Operation, @log_operation {
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)`.
|
||||
@@ -31,10 +31,10 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
|
||||
|
||||
/**
|
||||
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
|
||||
* a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingExpr`).
|
||||
* a logical 'or' (`LogicalOrExpr`), or a null-coalescing operation
|
||||
* (`NullCoalescingOperation`).
|
||||
*/
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr {
|
||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_operation {
|
||||
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
|
||||
* string NonNullOrEmpty(string s) {
|
||||
@@ -65,9 +70,7 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation,
|
||||
@null_coalescing_expr
|
||||
{
|
||||
class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr {
|
||||
override string getOperator() { result = "??" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
|
||||
@@ -77,7 +80,7 @@ class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation
|
||||
* A ternary logical operation, that is, a ternary conditional expression
|
||||
* (`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`
|
||||
|
||||
@@ -1,71 +1,6 @@
|
||||
/**
|
||||
* Provides classes for operations that also have compound assignment forms.
|
||||
*/
|
||||
deprecated module;
|
||||
|
||||
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 { }
|
||||
|
||||
@@ -1254,33 +1254,39 @@ case @expr.kind of
|
||||
|
||||
@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;
|
||||
@incr_op_expr = @pre_incr_expr | @post_incr_expr;
|
||||
@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;
|
||||
@bin_arith_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||
@bin_arith_operation = @mul_operation | @div_operation | @rem_operation | @add_operation | @sub_operation;
|
||||
|
||||
@ternary_log_op_expr = @conditional_expr;
|
||||
@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
|
||||
@un_log_op_expr = @log_not_expr;
|
||||
@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
|
||||
@incr_operation = @pre_incr_expr | @post_incr_expr;
|
||||
@decr_operation = @pre_decr_expr | @post_decr_expr;
|
||||
@mut_operation = @incr_operation | @decr_operation;
|
||||
@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
|
||||
| @rshift_expr | @urshift_expr;
|
||||
@un_bit_op_expr = @bit_not_expr;
|
||||
@bit_expr = @un_bit_op_expr | @bin_bit_op_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;
|
||||
@bin_bit_operation = @and_operation | @or_operation | @xor_operation | @lshift_operation
|
||||
| @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;
|
||||
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_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;
|
||||
@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
|
||||
@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
@ternary_operation = @ternary_log_operation;
|
||||
@bin_operation = @assign_expr | @bin_arith_operation | @bin_log_operation | @bin_bit_operation | @comp_expr;
|
||||
@un_operation = @un_arith_operation | @un_log_operation | @un_bit_operation | @sizeof_expr
|
||||
| @pointer_indirection_expr | @address_of_expr;
|
||||
|
||||
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Restructure and rename types related to operations.
|
||||
compatibility: full
|
||||
@@ -1,6 +1,7 @@
|
||||
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: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
|
||||
| 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
|
||||
|
||||
@@ -11,7 +11,7 @@ query predicate binarybitwise(
|
||||
}
|
||||
|
||||
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
|
||||
left = op.getLeftOperand() and
|
||||
|
||||
@@ -442,4 +442,31 @@ namespace My.Qltest
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
|
||||
// Test operator overloads
|
||||
public class N
|
||||
{
|
||||
public void operator +=(N y) => throw null;
|
||||
|
||||
public void operator checked +=(N y) => throw null;
|
||||
|
||||
public void M1(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
n += n0;
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
public void M2(N n)
|
||||
{
|
||||
var n0 = new N();
|
||||
checked
|
||||
{
|
||||
n += n0;
|
||||
}
|
||||
Sink(n);
|
||||
}
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,14 +32,16 @@ models
|
||||
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
||||
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
||||
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
||||
| 34 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 35 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
| 34 | Summary: My.Qltest; N; false; op_AdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 35 | Summary: My.Qltest; N; false; op_CheckedAdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 38 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||
| 39 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||
| 42 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||
| 43 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||
edges
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
||||
@@ -162,69 +164,77 @@ edges
|
||||
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:36 |
|
||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
||||
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
||||
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
||||
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:40 |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:42 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | provenance | MaD:34 |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | provenance | |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | provenance | |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | provenance | MaD:35 |
|
||||
nodes
|
||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||
@@ -443,6 +453,16 @@ nodes
|
||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | semmle.label | access to parameter n |
|
||||
subpaths
|
||||
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
||||
invalidModelRow
|
||||
@@ -489,3 +509,5 @@ invalidModelRow
|
||||
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | $@ | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | object creation of type N : N |
|
||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | $@ | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | object creation of type N : N |
|
||||
|
||||
@@ -53,6 +53,8 @@ extensions:
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_AdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["My.Qltest", "N", false, "op_CheckedAdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
|
||||
@@ -84,6 +84,10 @@ private module Ast implements AstSig<Location> {
|
||||
|
||||
class DoStmt = J::DoStmt;
|
||||
|
||||
class UntilStmt extends LoopStmt {
|
||||
UntilStmt() { none() }
|
||||
}
|
||||
|
||||
final private class FinalForStmt = J::ForStmt;
|
||||
|
||||
class ForStmt extends FinalForStmt {
|
||||
|
||||
@@ -331,7 +331,7 @@ public class B {
|
||||
x = new Object();
|
||||
}
|
||||
if(y instanceof String) {
|
||||
x.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ public class B {
|
||||
x = new Object();
|
||||
}
|
||||
if(!(y instanceof String)) {
|
||||
x.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ public class B {
|
||||
x = new Object();
|
||||
}
|
||||
if(y == z) {
|
||||
x.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
|
||||
Object x2 = null;
|
||||
@@ -359,7 +359,7 @@ public class B {
|
||||
x2 = new Object();
|
||||
}
|
||||
if(y != z) {
|
||||
x2.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x2.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
|
||||
Object x3 = null;
|
||||
@@ -367,7 +367,7 @@ public class B {
|
||||
x3 = new Object();
|
||||
}
|
||||
if(!(y == z)) {
|
||||
x3.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x3.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ public class B {
|
||||
cur = a[i];
|
||||
if (!prev) {
|
||||
// correctly guarded by !cur from the _previous_ iteration
|
||||
x.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
} else {
|
||||
x = new Object();
|
||||
}
|
||||
@@ -484,7 +484,7 @@ public class B {
|
||||
t = new Object();
|
||||
}
|
||||
// correctly guarded by t: null -> String -> Object
|
||||
x.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
x.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,7 +573,7 @@ public class B {
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
s.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
s.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // Spurious NPE - false positive
|
||||
// CFG reachability does not distinguish abrupt successors
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ public class C {
|
||||
long[][] a2 = null;
|
||||
boolean haveA2 = ix < len && (a2 = a1[ix]) != null;
|
||||
long[] a3 = null;
|
||||
final boolean haveA3 = haveA2 && (a3 = a2[ix]) != null; // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
if (haveA3) a3[0] = 0; // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
final boolean haveA3 = haveA2 && (a3 = a2[ix]) != null; // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
if (haveA3) a3[0] = 0; // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
}
|
||||
|
||||
public void ex2(boolean x, boolean y) {
|
||||
@@ -18,7 +18,7 @@ public class C {
|
||||
s2 = (s1 == null) ? null : "";
|
||||
}
|
||||
if (s2 != null)
|
||||
s1.hashCode(); // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
s1.hashCode(); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
}
|
||||
|
||||
public void ex3(List<String> ss) {
|
||||
@@ -48,7 +48,7 @@ public class C {
|
||||
slice = new ArrayList<>();
|
||||
result.add(slice);
|
||||
}
|
||||
slice.add(str); // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
slice.add(str); // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
++index;
|
||||
iter.remove();
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public class C {
|
||||
public void ex10(int[] a) {
|
||||
int n = a == null ? 0 : a.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int x = a[i]; // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
int x = a[i]; // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
if (x > 7)
|
||||
a = new int[n];
|
||||
}
|
||||
@@ -216,7 +216,7 @@ public class C {
|
||||
if (o1 == o2) {
|
||||
return;
|
||||
}
|
||||
if (o1.equals(o2)) { // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
if (o1.equals(o2)) { // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ public class C {
|
||||
public static void ex16(C c) {
|
||||
int[] xs = c.getFoo16() != null ? new int[5] : null;
|
||||
if (c.getFoo16() != null) {
|
||||
xs[0]++; // $ Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
xs[0]++; // $ SPURIOUS: Alert[java/dereferenced-value-may-be-null] // NPE - false positive
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,25 +11,25 @@ class UseBraces
|
||||
{
|
||||
int x = 0, y;
|
||||
int[] branches = new int[10];
|
||||
|
||||
|
||||
// If-then statement
|
||||
|
||||
|
||||
if(1==1)
|
||||
{
|
||||
f();
|
||||
}
|
||||
g(); // No alert
|
||||
|
||||
if(1==1)
|
||||
|
||||
if(1==1)
|
||||
f();
|
||||
g(); // No alert
|
||||
|
||||
|
||||
if(1==1)
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
|
||||
g();
|
||||
|
||||
if(1==1)
|
||||
f(); g(); // $ Alert // Alert
|
||||
f(); g(); // $ Alert
|
||||
|
||||
// If-then-else statement
|
||||
|
||||
@@ -41,29 +41,29 @@ class UseBraces
|
||||
{
|
||||
g();
|
||||
}
|
||||
|
||||
|
||||
g(); // No alert
|
||||
|
||||
|
||||
if(1==2)
|
||||
f();
|
||||
else
|
||||
g();
|
||||
f(); // No alert
|
||||
|
||||
|
||||
if(true)
|
||||
{
|
||||
f();
|
||||
}
|
||||
else
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
|
||||
g();
|
||||
|
||||
if(true)
|
||||
{
|
||||
f();
|
||||
}
|
||||
else
|
||||
f(); g(); // $ Alert // Alert
|
||||
f(); g(); // $ Alert
|
||||
|
||||
// While statement
|
||||
|
||||
@@ -80,44 +80,44 @@ class UseBraces
|
||||
|
||||
while(bb )
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
g();
|
||||
g(); // No alert
|
||||
|
||||
while(bb )
|
||||
f(); g(); // $ Alert // Alert
|
||||
f(); g(); // $ Alert
|
||||
|
||||
|
||||
while(bb)
|
||||
if (x != 0) x = 1;
|
||||
|
||||
// Do-while statement
|
||||
|
||||
|
||||
do
|
||||
f();
|
||||
while(false);
|
||||
g(); // No alert
|
||||
|
||||
|
||||
// For statement
|
||||
for(int i=0; i<10; ++i)
|
||||
{
|
||||
f();
|
||||
}
|
||||
g();
|
||||
|
||||
|
||||
for(int i=0; i<10; ++i)
|
||||
f();
|
||||
g();
|
||||
|
||||
|
||||
for(int i=0; i<10; ++i)
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
g();
|
||||
|
||||
for(int i=0; i<10; ++i)
|
||||
f(); g(); // $ Alert // Alert
|
||||
f(); g(); // $ Alert
|
||||
|
||||
|
||||
|
||||
// Foreach statement
|
||||
|
||||
|
||||
for( int b : branches)
|
||||
x += b;
|
||||
f();
|
||||
@@ -130,42 +130,42 @@ class UseBraces
|
||||
|
||||
for( int b : branches)
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
g();
|
||||
|
||||
for( int b : branches)
|
||||
f(); g(); // $ Alert // Alert
|
||||
f(); g(); // $ Alert
|
||||
|
||||
// Nested ifs
|
||||
if( true )
|
||||
if(false)
|
||||
f();
|
||||
g(); // No alert
|
||||
|
||||
|
||||
if( true )
|
||||
if(false) // $ Alert
|
||||
f();
|
||||
g(); // Alert
|
||||
|
||||
g();
|
||||
|
||||
if( true )
|
||||
;
|
||||
else
|
||||
else
|
||||
if (false)
|
||||
f();
|
||||
g(); // No alert
|
||||
|
||||
if( true )
|
||||
;
|
||||
else
|
||||
else
|
||||
if (false)
|
||||
f();
|
||||
g(); // false negative
|
||||
g(); // $ MISSING: Alert // false negative
|
||||
|
||||
if( true )
|
||||
;
|
||||
else if (false)
|
||||
f(); // $ Alert
|
||||
g(); // Alert
|
||||
|
||||
g();
|
||||
|
||||
// Nested combinations
|
||||
if (true)
|
||||
while (x<10)
|
||||
@@ -175,7 +175,7 @@ class UseBraces
|
||||
if (true)
|
||||
while (x<10) // $ Alert
|
||||
f();
|
||||
g(); // Alert
|
||||
g();
|
||||
|
||||
while (x<10)
|
||||
if (true)
|
||||
@@ -185,7 +185,7 @@ class UseBraces
|
||||
while (x<10)
|
||||
if (true) // $ Alert
|
||||
f();
|
||||
g(); // Alert
|
||||
g();
|
||||
|
||||
if (true)
|
||||
f();
|
||||
|
||||
@@ -62,10 +62,10 @@ public class ResponseSplitting extends HttpServlet {
|
||||
response.setHeader("h", t.replace('\n', ' ').replace('\r', ' '));
|
||||
|
||||
// FALSE NEGATIVE: replace only some line breaks
|
||||
response.setHeader("h", t.replace('\n', ' '));
|
||||
response.setHeader("h", t.replace('\n', ' ')); // $ MISSING: Alert
|
||||
|
||||
// FALSE NEGATIVE: replace only some line breaks
|
||||
response.setHeader("h", t.replaceAll("\r", ""));
|
||||
response.setHeader("h", t.replaceAll("\r", "")); // $ MISSING: Alert
|
||||
|
||||
// GOOD: replace all linebreaks with a simple regex
|
||||
response.setHeader("h", t.replaceAll("\n", "").replaceAll("\r", ""));
|
||||
|
||||
@@ -78,7 +78,7 @@ public class ArithmeticTainted {
|
||||
// FALSE NEGATIVE: stillTainted could still be very large, even
|
||||
// after
|
||||
// it has had arithmetic done on it
|
||||
int output = stillTainted + 100;
|
||||
int output = stillTainted + 100; // $ MISSING: Alert[java/tainted-arithmetic]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class ArithmeticTainted {
|
||||
}
|
||||
int output = data + 1;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
double x= Double.MAX_VALUE;
|
||||
// OK: CWE-190 only pertains to integer arithmetic
|
||||
|
||||
@@ -84,7 +84,7 @@ class Test {
|
||||
// FALSE POSITIVE: the query check purely based on the type, it
|
||||
// can't try to
|
||||
// determine whether the value may in fact always be in bounds
|
||||
i += j; // $ Alert[java/implicit-cast-in-compound-assignment]
|
||||
i += j; // $ SPURIOUS: Alert[java/implicit-cast-in-compound-assignment]
|
||||
}
|
||||
|
||||
// ArithmeticWithExtremeValues
|
||||
@@ -224,7 +224,7 @@ class Test {
|
||||
// FALSE NEGATIVE: stillLarge could still be very large, even
|
||||
// after
|
||||
// it has had arithmetic done on it
|
||||
int output = stillLarge + 100;
|
||||
int output = stillLarge + 100; // $ MISSING: Alert[java/uncontrolled-arithmetic]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class Test {
|
||||
// FALSE NEGATIVE: stillLarge could still be very large, even
|
||||
// after
|
||||
// it has had arithmetic done on it
|
||||
int output = stillLarge + 100;
|
||||
int output = stillLarge + 100; // $ MISSING: Alert[java/uncontrolled-arithmetic]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ interface Hello extends java.rmi.Remote {
|
||||
|
||||
class HelloImpl implements Hello {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
try {
|
||||
// HttpsUrls
|
||||
{
|
||||
String protocol = "http://"; // $ Source[java/non-https-url]
|
||||
@@ -31,7 +31,7 @@ class HelloImpl implements Hello {
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String protocol = "http"; // $ Source[java/non-https-url]
|
||||
URL u = new URL(protocol, "www.secret.example.org", "foo");
|
||||
@@ -44,7 +44,7 @@ class HelloImpl implements Hello {
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String protocol = "http://"; // $ Source[java/non-https-url]
|
||||
// the second URL overwrites the first, as it has a protocol
|
||||
@@ -58,7 +58,7 @@ class HelloImpl implements Hello {
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String protocol = "https://";
|
||||
URL u = new URL(protocol + "www.secret.example.org/");
|
||||
@@ -70,7 +70,7 @@ class HelloImpl implements Hello {
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String protocol = "https";
|
||||
URL u = new URL(protocol, "www.secret.example.org", "foo");
|
||||
@@ -82,27 +82,27 @@ class HelloImpl implements Hello {
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String protocol = "http"; // $ Source[java/non-https-url]
|
||||
String protocol = "http"; // $ SPURIOUS: Source[java/non-https-url]
|
||||
URL u = new URL(protocol, "internal-url", "foo");
|
||||
// FALSE POSITIVE: the query has no way of knowing whether the url will
|
||||
// resolve to somewhere outside the internal network, where there
|
||||
// are unlikely to be interception attempts
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection(); // $ Alert[java/non-https-url]
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection(); // $ SPURIOUS: Alert[java/non-https-url]
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String input = "URL is: http://www.secret-example.org";
|
||||
String url = input.substring(8);
|
||||
URL u = new URL(url);
|
||||
// FALSE NEGATIVE: we cannot tell that the substring results in a url
|
||||
// string
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection(); // $ MISSING: Alert[java/non-https-url]
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
|
||||
@@ -119,6 +119,12 @@ signature module AstSig<LocationSig Location> {
|
||||
Expr getCondition();
|
||||
}
|
||||
|
||||
/** An `until` loop statement. */
|
||||
class UntilStmt extends LoopStmt {
|
||||
/** Gets the boolean condition of this `until` loop. */
|
||||
Expr getCondition();
|
||||
}
|
||||
|
||||
/** A traditional C-style `for` loop. */
|
||||
class ForStmt extends LoopStmt {
|
||||
/** Gets the initializer of the loop at the specified (zero-based) position, if any. */
|
||||
@@ -608,6 +614,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
|
||||
any(IfStmt ifstmt).getCondition() = n or
|
||||
any(WhileStmt whilestmt).getCondition() = n or
|
||||
any(DoStmt dostmt).getCondition() = n or
|
||||
any(UntilStmt untilstmt).getCondition() = n or
|
||||
any(ForStmt forstmt).getCondition() = n or
|
||||
any(ConditionalExpr condexpr).getCondition() = n or
|
||||
any(CatchClause catch).getCondition() = n or
|
||||
@@ -1513,7 +1520,12 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
|
||||
n2.isBefore(ifstmt.getCondition())
|
||||
or
|
||||
n1.isAfterTrue(ifstmt.getCondition()) and
|
||||
n2.isBefore(ifstmt.getThen())
|
||||
(
|
||||
n2.isBefore(ifstmt.getThen())
|
||||
or
|
||||
not exists(ifstmt.getThen()) and
|
||||
n2.isAfter(ifstmt)
|
||||
)
|
||||
or
|
||||
n1.isAfterFalse(ifstmt.getCondition()) and
|
||||
(
|
||||
@@ -1530,9 +1542,9 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
|
||||
n2.isAfter(ifstmt)
|
||||
)
|
||||
or
|
||||
exists(WhileStmt whilestmt |
|
||||
n1.isBefore(whilestmt) and
|
||||
n2.isAdditional(whilestmt, loopHeaderTag())
|
||||
exists(LoopStmt loopstmt | loopstmt instanceof WhileStmt or loopstmt instanceof UntilStmt |
|
||||
n1.isBefore(loopstmt) and
|
||||
n2.isAdditional(loopstmt, loopHeaderTag())
|
||||
)
|
||||
or
|
||||
exists(DoStmt dostmt |
|
||||
@@ -1540,16 +1552,20 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
|
||||
n2.isBefore(dostmt.getBody())
|
||||
)
|
||||
or
|
||||
exists(LoopStmt loopstmt, AstNode cond |
|
||||
loopstmt.(WhileStmt).getCondition() = cond or loopstmt.(DoStmt).getCondition() = cond
|
||||
exists(LoopStmt loopstmt, AstNode cond, boolean while |
|
||||
loopstmt.(WhileStmt).getCondition() = cond and while = true
|
||||
or
|
||||
loopstmt.(DoStmt).getCondition() = cond and while = true
|
||||
or
|
||||
loopstmt.(UntilStmt).getCondition() = cond and while = false
|
||||
|
|
||||
n1.isAdditional(loopstmt, loopHeaderTag()) and
|
||||
n2.isBefore(cond)
|
||||
or
|
||||
n1.isAfterTrue(cond) and
|
||||
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while)) and
|
||||
n2.isBefore(loopstmt.getBody())
|
||||
or
|
||||
n1.isAfterFalse(cond) and
|
||||
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while.booleanNot())) and
|
||||
n2.isAfter(loopstmt)
|
||||
or
|
||||
n1.isAfter(loopstmt.getBody()) and
|
||||
|
||||
@@ -333,6 +333,9 @@ pub fn extract(
|
||||
.run_from_tree(&tree, source)
|
||||
.unwrap_or_else(|e| panic!("Desugaring failed for {path_str}: {e}"));
|
||||
traverse_yeast(&ast, &mut visitor);
|
||||
// Comments and other `extra` nodes are not represented in the desugared
|
||||
// AST, so recover them directly from the original parse tree.
|
||||
traverse_extras(&tree, &mut visitor);
|
||||
} else {
|
||||
traverse(&tree, &mut visitor);
|
||||
}
|
||||
@@ -365,6 +368,8 @@ struct Visitor<'a> {
|
||||
ast_node_parent_table_name: String,
|
||||
/// Language-specific name of the tokeninfo table
|
||||
tokeninfo_table_name: String,
|
||||
/// Language-specific name of the trivia tokeninfo table
|
||||
trivia_tokeninfo_table_name: String,
|
||||
/// A lookup table from type name to node types
|
||||
schema: &'a NodeTypeMap,
|
||||
/// A stack for gathering information from child nodes. Whenever a node is
|
||||
@@ -395,11 +400,33 @@ impl<'a> Visitor<'a> {
|
||||
ast_node_location_table_name: format!("{language_prefix}_ast_node_location"),
|
||||
ast_node_parent_table_name: format!("{language_prefix}_ast_node_parent"),
|
||||
tokeninfo_table_name: format!("{language_prefix}_tokeninfo"),
|
||||
trivia_tokeninfo_table_name: format!("{language_prefix}_trivia_tokeninfo"),
|
||||
schema,
|
||||
stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a `TriviaToken` for the given `extra` node (e.g. a comment) from
|
||||
/// the original parse tree. Trivia tokens carry a location and their source
|
||||
/// text, but are not attached to a parent in the (possibly desugared) AST.
|
||||
fn emit_trivia_token(&mut self, node: &Node) {
|
||||
let id = self.trap_writer.fresh_id();
|
||||
let loc = location_for(self, self.file_label, node);
|
||||
let loc_label = location_label(self.trap_writer, loc);
|
||||
self.trap_writer.add_tuple(
|
||||
&self.ast_node_location_table_name,
|
||||
vec![trap::Arg::Label(id), trap::Arg::Label(loc_label)],
|
||||
);
|
||||
self.trap_writer.add_tuple(
|
||||
&self.trivia_tokeninfo_table_name,
|
||||
vec![
|
||||
trap::Arg::Label(id),
|
||||
trap::Arg::Int(node.kind_id() as usize),
|
||||
sliced_source_arg(self.source, node),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
fn record_parse_error(&mut self, loc: trap::Label, mesg: &diagnostics::DiagnosticMessage) {
|
||||
self.diagnostics_writer.write(mesg);
|
||||
let id = self.trap_writer.fresh_id();
|
||||
@@ -835,6 +862,24 @@ fn traverse(tree: &Tree, visitor: &mut Visitor) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the original tree-sitter tree and emits a `TriviaToken` for every
|
||||
/// `extra` node (e.g. a comment). Used to preserve comments that would
|
||||
/// otherwise be lost after a desugaring pass rewrites the tree.
|
||||
fn traverse_extras(tree: &Tree, visitor: &mut Visitor) {
|
||||
emit_extras_in(visitor, tree.root_node());
|
||||
}
|
||||
|
||||
fn emit_extras_in(visitor: &mut Visitor, node: Node<'_>) {
|
||||
let mut cursor = node.walk();
|
||||
for child in node.children(&mut cursor) {
|
||||
if child.is_extra() {
|
||||
visitor.emit_trivia_token(&child);
|
||||
} else {
|
||||
emit_extras_in(visitor, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn traverse_yeast(tree: &yeast::Ast, visitor: &mut Visitor) {
|
||||
use yeast::Cursor;
|
||||
let mut cursor = tree.walk();
|
||||
|
||||
@@ -68,7 +68,12 @@ pub fn generate(
|
||||
let node_parent_table_name = format!("{}_ast_node_parent", &prefix);
|
||||
let token_name = format!("{}_token", &prefix);
|
||||
let tokeninfo_name = format!("{}_tokeninfo", &prefix);
|
||||
let trivia_token_name = format!("{}_trivia_token", &prefix);
|
||||
let trivia_tokeninfo_name = format!("{}_trivia_tokeninfo", &prefix);
|
||||
let reserved_word_name = format!("{}_reserved_word", &prefix);
|
||||
// When a desugaring is configured, comments and other `extra` nodes are
|
||||
// preserved from the original parse tree as `TriviaToken`s.
|
||||
let has_trivia_tokens = language.desugar.is_some();
|
||||
let effective_node_types: String = match language
|
||||
.desugar
|
||||
.as_ref()
|
||||
@@ -85,28 +90,35 @@ pub fn generate(
|
||||
let nodes = node_types::read_node_types_str(&prefix, &effective_node_types)?;
|
||||
let (dbscheme_entries, mut ast_node_members, token_kinds) = convert_nodes(&nodes);
|
||||
ast_node_members.insert(&token_name);
|
||||
if has_trivia_tokens {
|
||||
ast_node_members.insert(&trivia_token_name);
|
||||
}
|
||||
writeln!(&mut dbscheme_writer, "/*- {} dbscheme -*/", language.name)?;
|
||||
dbscheme::write(&mut dbscheme_writer, &dbscheme_entries)?;
|
||||
let token_case = create_token_case(&token_name, token_kinds);
|
||||
dbscheme::write(
|
||||
&mut dbscheme_writer,
|
||||
&[
|
||||
dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)),
|
||||
dbscheme::Entry::Case(token_case),
|
||||
dbscheme::Entry::Union(dbscheme::Union {
|
||||
name: &ast_node_name,
|
||||
members: ast_node_members,
|
||||
}),
|
||||
dbscheme::Entry::Table(create_ast_node_location_table(
|
||||
&node_location_table_name,
|
||||
&ast_node_name,
|
||||
)),
|
||||
dbscheme::Entry::Table(create_ast_node_parent_table(
|
||||
&node_parent_table_name,
|
||||
&ast_node_name,
|
||||
)),
|
||||
],
|
||||
)?;
|
||||
let mut dbscheme_tail = vec![
|
||||
dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)),
|
||||
dbscheme::Entry::Case(token_case),
|
||||
];
|
||||
if has_trivia_tokens {
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_tokeninfo(
|
||||
&trivia_tokeninfo_name,
|
||||
&trivia_token_name,
|
||||
)));
|
||||
}
|
||||
dbscheme_tail.push(dbscheme::Entry::Union(dbscheme::Union {
|
||||
name: &ast_node_name,
|
||||
members: ast_node_members,
|
||||
}));
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_ast_node_location_table(
|
||||
&node_location_table_name,
|
||||
&ast_node_name,
|
||||
)));
|
||||
dbscheme_tail.push(dbscheme::Entry::Table(create_ast_node_parent_table(
|
||||
&node_parent_table_name,
|
||||
&ast_node_name,
|
||||
)));
|
||||
dbscheme::write(&mut dbscheme_writer, &dbscheme_tail)?;
|
||||
|
||||
let mut body = vec![
|
||||
ql::TopLevel::Class(ql_gen::create_ast_node_class(
|
||||
@@ -116,6 +128,12 @@ pub fn generate(
|
||||
)),
|
||||
ql::TopLevel::Class(ql_gen::create_token_class(&token_name, &tokeninfo_name)),
|
||||
];
|
||||
if has_trivia_tokens {
|
||||
body.push(ql::TopLevel::Class(ql_gen::create_trivia_token_class(
|
||||
&trivia_token_name,
|
||||
&trivia_tokeninfo_name,
|
||||
)));
|
||||
}
|
||||
// Only emit the ReservedWord class when there are actually unnamed token
|
||||
// types in the schema (i.e., @{prefix}_reserved_word exists in the dbscheme).
|
||||
// When converting from a YEAST YAML schema that has no unnamed tokens, this
|
||||
|
||||
@@ -199,6 +199,70 @@ pub fn create_token_class<'a>(token_type: &'a str, tokeninfo: &'a str) -> ql::Cl
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the `TriviaToken` class. Trivia tokens (e.g. comments) are
|
||||
/// `extra` nodes preserved from the original parse tree even when the tree has
|
||||
/// been rewritten by a desugaring pass. They are not part of the regular
|
||||
/// `Token` hierarchy because they do not appear in the (possibly desugared)
|
||||
/// output schema.
|
||||
pub fn create_trivia_token_class<'a>(
|
||||
trivia_token_type: &'a str,
|
||||
trivia_tokeninfo: &'a str,
|
||||
) -> ql::Class<'a> {
|
||||
let trivia_tokeninfo_arity = 3; // id, kind, value
|
||||
let get_value = ql::Predicate {
|
||||
qldoc: Some(String::from("Gets the source text of this trivia token.")),
|
||||
name: "getValue",
|
||||
overridden: false,
|
||||
is_private: false,
|
||||
is_final: true,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage(
|
||||
"result",
|
||||
trivia_tokeninfo,
|
||||
1,
|
||||
trivia_tokeninfo_arity,
|
||||
),
|
||||
overlay: None,
|
||||
};
|
||||
let to_string = ql::Predicate {
|
||||
qldoc: Some(String::from(
|
||||
"Gets a string representation of this element.",
|
||||
)),
|
||||
name: "toString",
|
||||
overridden: true,
|
||||
is_private: false,
|
||||
is_final: true,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: ql::Expression::Equals(
|
||||
Box::new(ql::Expression::Var("result")),
|
||||
Box::new(ql::Expression::Dot(
|
||||
Box::new(ql::Expression::Var("this")),
|
||||
"getValue",
|
||||
vec![],
|
||||
)),
|
||||
),
|
||||
overlay: None,
|
||||
};
|
||||
ql::Class {
|
||||
qldoc: Some(String::from(
|
||||
"A trivia token, such as a comment, preserved from the original parse tree.",
|
||||
)),
|
||||
name: "TriviaToken",
|
||||
is_abstract: false,
|
||||
supertypes: vec![ql::Type::At(trivia_token_type), ql::Type::Normal("AstNode")]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
characteristic_predicate: None,
|
||||
predicates: vec![
|
||||
get_value,
|
||||
to_string,
|
||||
create_get_a_primary_ql_class("TriviaToken", false),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the `ReservedWord` class.
|
||||
pub fn create_reserved_word_class(db_name: &str) -> ql::Class<'_> {
|
||||
let class_name = "ReservedWord";
|
||||
|
||||
@@ -61,6 +61,18 @@ module Unified {
|
||||
override string getAPrimaryQlClass() { result = "Token" }
|
||||
}
|
||||
|
||||
/** A trivia token, such as a comment, preserved from the original parse tree. */
|
||||
class TriviaToken extends @unified_trivia_token, AstNode {
|
||||
/** Gets the source text of this trivia token. */
|
||||
final string getValue() { unified_trivia_tokeninfo(this, _, result) }
|
||||
|
||||
/** Gets a string representation of this element. */
|
||||
final override string toString() { result = this.getValue() }
|
||||
|
||||
/** Gets the name of the primary QL class for this element. */
|
||||
override string getAPrimaryQlClass() { result = "TriviaToken" }
|
||||
}
|
||||
|
||||
/** Gets the file containing the given `node`. */
|
||||
private @file getNodeFile(@unified_ast_node node) {
|
||||
exists(@location_default loc | unified_ast_node_location(node, loc) |
|
||||
|
||||
18
unified/ql/lib/codeql/unified/Comments.qll
Normal file
18
unified/ql/lib/codeql/unified/Comments.qll
Normal file
@@ -0,0 +1,18 @@
|
||||
/** Provides classes for working with comments. */
|
||||
|
||||
private import unified
|
||||
|
||||
/**
|
||||
* A comment appearing in the source code.
|
||||
*/
|
||||
class Comment extends TriviaToken {
|
||||
// At the moment, comments are the only type trivia token we extract
|
||||
/**
|
||||
* Gets the text inside this comment, not counting the delimeters.
|
||||
*/
|
||||
string getCommentText() {
|
||||
result = this.getValue().regexpCapture("//(.*)", 1)
|
||||
or
|
||||
result = this.getValue().regexpCapture("(?s)/\\*(.*)\\*/", 1)
|
||||
}
|
||||
}
|
||||
@@ -334,7 +334,13 @@ case @unified_token.kind of
|
||||
;
|
||||
|
||||
|
||||
@unified_ast_node = @unified_apply_pattern | @unified_binary_expr | @unified_block_stmt | @unified_call_expr | @unified_expr_condition | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_lambda_expr | @unified_let_pattern_condition | @unified_member_access_expr | @unified_name_expr | @unified_parameter | @unified_sequence_condition | @unified_token | @unified_top_level | @unified_tuple_pattern | @unified_unary_expr | @unified_var_pattern | @unified_variable_declaration_stmt | @unified_variable_declarator
|
||||
unified_trivia_tokeninfo(
|
||||
unique int id: @unified_trivia_token,
|
||||
int kind: int ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
@unified_ast_node = @unified_apply_pattern | @unified_binary_expr | @unified_block_stmt | @unified_call_expr | @unified_expr_condition | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_lambda_expr | @unified_let_pattern_condition | @unified_member_access_expr | @unified_name_expr | @unified_parameter | @unified_sequence_condition | @unified_token | @unified_top_level | @unified_trivia_token | @unified_tuple_pattern | @unified_unary_expr | @unified_var_pattern | @unified_variable_declaration_stmt | @unified_variable_declarator
|
||||
|
||||
unified_ast_node_location(
|
||||
unique int node: @unified_ast_node ref,
|
||||
|
||||
8
unified/ql/lib/unified.qll
Normal file
8
unified/ql/lib/unified.qll
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Provides classes for working with the AST, as well as files and locations.
|
||||
*/
|
||||
|
||||
import codeql.Locations
|
||||
import codeql.files.FileSystem
|
||||
import codeql.unified.Ast::Unified
|
||||
import codeql.unified.Comments
|
||||
3
unified/ql/test/library-tests/comments/comments.expected
Normal file
3
unified/ql/test/library-tests/comments/comments.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
| comments.swift:1:1:1:22 | // Hello this is swift | Hello this is swift |
|
||||
| comments.swift:3:1:6:3 | /*\n * This is a multi-line comment\n * It should be ignored by the parser\n */ | \n * This is a multi-line comment\n * It should be ignored by the parser\n |
|
||||
| comments.swift:9:5:9:36 | // This is a single-line comment | This is a single-line comment |
|
||||
3
unified/ql/test/library-tests/comments/comments.ql
Normal file
3
unified/ql/test/library-tests/comments/comments.ql
Normal file
@@ -0,0 +1,3 @@
|
||||
import unified
|
||||
|
||||
query predicate comments(Comment c, string text) { text = c.getCommentText() }
|
||||
11
unified/ql/test/library-tests/comments/comments.swift
Normal file
11
unified/ql/test/library-tests/comments/comments.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
// Hello this is swift
|
||||
|
||||
/*
|
||||
* This is a multi-line comment
|
||||
* It should be ignored by the parser
|
||||
*/
|
||||
|
||||
func hello() {
|
||||
// This is a single-line comment
|
||||
print("Hello, world!")
|
||||
}
|
||||
Reference in New Issue
Block a user