Merge pull request #1406 from taus-semmle/mergeback-rc/1.21

Merge `rc/1.21` into `master`
This commit is contained in:
Max Schaefer 2019-06-05 16:33:50 +01:00 коммит произвёл GitHub
Родитель 98eced973e f7a092882b
Коммит e11406ca90
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
55 изменённых файлов: 4179 добавлений и 71 удалений

Просмотреть файл

@ -13,6 +13,10 @@
* The following C# 8 features are now extracted:
- Range expressions
- Recursive patterns
- Using declaration statements
- `static` modifiers on local functions
- Null-coalescing assignment expressions
* The `unmanaged` type parameter constraint is now extracted.
## Changes to QL libraries
@ -20,6 +24,7 @@
* The class `Attribute` has two new predicates: `getConstructorArgument()` and `getNamedArgument()`. The first predicate returns arguments to the underlying constructor call and the latter returns named arguments for initializing fields and properties.
* The class `TypeParameterConstraints` has a new predicate `hasUnmanagedTypeConstraint()`, indicating that the type parameter has the `unmanaged` constraint.
* The following QL classes have been added to model C# 8 features:
- Class `AssignCoalesceExpr` models null-coalescing assignment, for example `x ??= y`
- Class `IndexExpr` models from-end index expressions, for example `^1`
- Class `PatternExpr` is an `Expr` that appears in a pattern. It has the new subclasses `DiscardPatternExpr`, `LabeledPatternExpr`, `RecursivePatternExpr`, `TypeAccessPatternExpr`, `TypePatternExpr`, and `VariablePatternExpr`.
- Class `PatternMatch` models a pattern being matched. It has the subclasses `Case` and `IsExpr`.
@ -31,5 +36,6 @@
- Classes `IsConstantExpr`, `IsTypeExpr` and `IsPatternExpr` are deprecated in favour of `IsExpr`
- Class `Switch` models both `SwitchExpr` and `SwitchStmt`
- Class `Case` models both `CaseStmt` and `SwitchCaseExpr`
- Class `UsingStmt` models both `UsingBlockStmt` and `UsingDeclStmt`
## Changes to autobuilder

Просмотреть файл

@ -40,7 +40,7 @@
| Expression has no effect | Fewer false-positive results | This rule now treats uses of `Object.defineProperty` more conservatively. |
| Incomplete regular expression for hostnames | More results | This rule now tracks regular expressions for host names further. |
| Incomplete string escaping or encoding | More results | This rule now considers the flow of regular expressions literals, and it no longer flags the removal of trailing newlines. |
| Password in configuration file | Fewer false positive results | This query now excludes passwords that are inserted into the configuration file using a templating mechanism or read from environment variables. |
| Password in configuration file | Fewer false positive results | This query now excludes passwords that are inserted into the configuration file using a templating mechanism or read from environment variables. Results are no longer shown on LGTM by default. |
| Replacement of a substring with itself | More results | This rule now considers the flow of regular expressions literals. |
| Server-side URL redirect | Fewer false-positive results | This rule now treats URLs as safe in more cases where the hostname cannot be tampered with. |
| Type confusion through parameter tampering | Fewer false-positive results | This rule now recognizes additional emptiness checks. |

Просмотреть файл

@ -71,6 +71,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ExprKind.ASSIGN_LSHIFT;
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
return ExprKind.ASSIGN_RSHIFT;
case SyntaxKind.QuestionQuestionEqualsToken:
return ExprKind.ASSIGN_COALESCE;
default:
cx.ModelError(syntax, "Unrecognised assignment type " + GetKind(cx, syntax));
return ExprKind.UNKNOWN;
@ -142,6 +144,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ExprKind.SUB;
case ExprKind.ASSIGN_XOR:
return ExprKind.BIT_XOR;
case ExprKind.ASSIGN_COALESCE:
return ExprKind.NULL_COALESCING;
default:
cx.ModelError(Syntax, "Couldn't unfold assignment of type " + kind);
return ExprKind.UNKNOWN;

Просмотреть файл

@ -80,6 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SyntaxKind.RightShiftAssignmentExpression:
case SyntaxKind.DivideAssignmentExpression:
case SyntaxKind.ModuloAssignmentExpression:
case SyntaxKind.CoalesceAssignmentExpression:
return Assignment.Create(info);
case SyntaxKind.ObjectCreationExpression:

Просмотреть файл

@ -1,4 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
{
@ -39,6 +41,18 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate()
{
PopulateMethod();
// There is a "bug" in Roslyn whereby the IMethodSymbol associated with the local function symbol
// is always static, so we need to go to the syntax reference of the local function to see whether
// the "static" modifier is present.
if (symbol.DeclaringSyntaxReferences.SingleOrDefault().GetSyntax() is LocalFunctionStatementSyntax fn)
{
foreach(var modifier in fn.Modifiers)
{
Modifier.HasModifier(Context, this, modifier.Text);
}
}
var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
var returnType = Type.Create(Context, symbol.ReturnType);
Context.Emit(Tuples.local_functions(this, symbol.Name, returnType, originalDefinition));

Просмотреть файл

@ -6,8 +6,19 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
{
class LocalDeclaration : Statement<LocalDeclarationStatementSyntax>
{
static StmtKind GetKind(LocalDeclarationStatementSyntax declStmt)
{
if (declStmt.UsingKeyword.RawKind != 0)
return StmtKind.USING_DECL;
if (declStmt.IsConst)
return StmtKind.CONST_DECL;
return StmtKind.VAR_DECL;
}
LocalDeclaration(Context cx, LocalDeclarationStatementSyntax declStmt, IStatementParentEntity parent, int child)
: base(cx, declStmt, declStmt.IsConst ? StmtKind.CONST_DECL : StmtKind.VAR_DECL, parent, child) { }
: base(cx, declStmt, GetKind(declStmt), parent, child) { }
public static LocalDeclaration Create(Context cx, LocalDeclarationStatementSyntax node, IStatementParentEntity parent, int child)
{

Просмотреть файл

@ -112,6 +112,7 @@ namespace Semmle.Extraction.Kinds
RECURSIVE_PATTERN = 115,
PROPERTY_PATTERN = 116,
POSITIONAL_PATTERN = 117,
SWITCH_CASE = 118
SWITCH_CASE = 118,
ASSIGN_COALESCE = 119
}
}

Просмотреть файл

@ -34,6 +34,7 @@ namespace Semmle.Extraction.Kinds // lgtm[cs/similar-file]
LABEL = 27,
CATCH = 28,
CASE = 29,
LOCAL_FUNCTION = 30
LOCAL_FUNCTION = 30,
USING_DECL = 31
}
}

Просмотреть файл

@ -903,7 +903,7 @@ class ExplicitConversionOperator extends ConversionOperator {
* }
* ```
*/
class LocalFunction extends Callable, @local_function {
class LocalFunction extends Callable, Modifiable, @local_function {
override string getName() { local_functions(this, result, _, _) }
override LocalFunction getSourceDeclaration() { local_functions(this, _, _, result) }

Просмотреть файл

@ -1115,40 +1115,16 @@ class LockStmt extends Stmt, @lock_stmt {
}
/**
* A `using` statement, for example
*
* ```
* using (FileStream f = File.Open("settings.xml")) {
* ...
* }
* ```
* A using block or declaration. Either a using declaration (`UsingDeclStmt`) or
* a using block (`UsingBlockStmt`).
*/
class UsingStmt extends Stmt, @using_stmt {
/** Gets the `i`th local variable of this `using` statement. */
LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() }
/** Gets a local variable of this `using` statement. */
LocalVariable getAVariable() { result = this.getVariable(_) }
/** Gets the `i`th local variable declaration of this `using` statement. */
LocalVariableDeclExpr getVariableDeclExpr(int i) { result = this.getChild(-i - 1) }
LocalVariableDeclExpr getVariableDeclExpr(int i) { none() }
/** Gets a local variable declaration of this `using` statement. */
LocalVariableDeclExpr getAVariableDeclExpr() { result = this.getVariableDeclExpr(_) }
/**
* Gets the expression directly used by this `using` statement, if any. For
* example, `f` on line 2 in
*
* ```
* var f = File.Open("settings.xml");
* using (f) {
* ...
* }
* ```
*/
Expr getExpr() { result = this.getChild(0) }
/**
* Gets an expression that is used in this `using` statement. Either an
* expression assigned to a variable, for example `File.Open("settings.xml")`
@ -1169,14 +1145,69 @@ class UsingStmt extends Stmt, @using_stmt {
* }
* ```
*/
Expr getAnExpr() {
Expr getAnExpr() { none() }
/**
* DEPRECATED: Use UsingBlockStmt.getExpr() instead.
* Gets the expression directly used by this `using` statement, if any. For
* example, `f` on line 2 in
*
* ```
* var f = File.Open("settings.xml");
* using (f) {
* ...
* }
* ```
*/
deprecated Expr getExpr() { none() }
/**
* DEPRECATED: Use UsingBlockStmt.getBody() instead.
* Gets the body of this `using` statement.
*/
deprecated Stmt getBody() { none() }
}
/**
* A `using` block statement, for example
*
* ```
* using (FileStream f = File.Open("settings.xml")) {
* ...
* }
* ```
*/
class UsingBlockStmt extends UsingStmt, @using_block_stmt {
/** Gets the `i`th local variable of this `using` statement. */
LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() }
/** Gets a local variable of this `using` statement. */
LocalVariable getAVariable() { result = this.getVariable(_) }
/** Gets the `i`th local variable declaration of this `using` statement. */
override LocalVariableDeclExpr getVariableDeclExpr(int i) { result = this.getChild(-i - 1) }
/**
* Gets the expression directly used by this `using` statement, if any. For
* example, `f` on line 2 in
*
* ```
* var f = File.Open("settings.xml");
* using (f) {
* ...
* }
* ```
*/
override Expr getExpr() { result = this.getChild(0) }
override Expr getAnExpr() {
result = this.getAVariableDeclExpr().getInitializer()
or
result = this.getExpr()
}
/** Gets the body of this `using` statement. */
Stmt getBody() { result.getParent() = this }
override Stmt getBody() { result.getParent() = this }
override string toString() { result = "using (...) {...}" }
}
@ -1254,6 +1285,29 @@ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt {
override string toString() { result = "const ... ...;" }
}
/**
* A `using` declaration statement, for example
*
* ```
* using FileStream f = File.Open("settings.xml");
* ```
*/
class UsingDeclStmt extends LocalVariableDeclStmt, UsingStmt, @using_decl_stmt {
override string toString() { result = "using ... ...;" }
override LocalVariableDeclExpr getAVariableDeclExpr() {
result = LocalVariableDeclStmt.super.getAVariableDeclExpr()
}
override LocalVariableDeclExpr getVariableDeclExpr(int n) {
result = LocalVariableDeclStmt.super.getVariableDeclExpr(n)
}
override Expr getAnExpr() {
result = this.getAVariableDeclExpr().getInitializer()
}
}
/**
* An empty statement, for example line 2 in
*

Просмотреть файл

@ -468,7 +468,7 @@ module ControlFlow {
override ControlFlowElement getChildElement(int i) {
not this instanceof GeneralCatchClause and
not this instanceof FixedStmt and
not this instanceof UsingStmt and
not this instanceof UsingBlockStmt and
result = this.getChild(i)
or
this = any(GeneralCatchClause gcc | i = 0 and result = gcc.getBlock())
@ -480,7 +480,7 @@ module ControlFlow {
i = max(int j | exists(fs.getVariableDeclExpr(j))) + 1
)
or
this = any(UsingStmt us |
this = any(UsingBlockStmt us |
if exists(us.getExpr())
then (
result = us.getExpr() and

Просмотреть файл

@ -230,3 +230,10 @@ class AddEventExpr extends AddOrRemoveEventExpr, @add_event_expr {
class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
override string toString() { result = "... -= ..." }
}
/**
* A null-coalescing assignment operation, for example `x ??= y`.
*/
class AssignCoalesceExpr extends AssignOperation, @assign_coalesce_expr {
override string toString() { result = "... ??= ..." }
}

Просмотреть файл

@ -526,7 +526,7 @@ specific_type_parameter_constraints(
@modifiable = @modifiable_direct | @event_accessor;
@modifiable_direct = @member | @accessor;
@modifiable_direct = @member | @accessor | @local_function;
modifiers(
unique int id: @modifier,
@ -798,7 +798,7 @@ case @stmt.kind of
| 18 = @checked_stmt
| 19 = @unchecked_stmt
| 20 = @lock_stmt
| 21 = @using_stmt
| 21 = @using_block_stmt
| 22 = @var_decl_stmt
| 23 = @const_decl_stmt
| 24 = @empty_stmt
@ -808,11 +808,14 @@ case @stmt.kind of
| 28 = @catch
| 29 = @case_stmt
| 30 = @local_function_stmt
| 31 = @using_decl_stmt
;
@using_stmt = @using_block_stmt | @using_decl_stmt;
@labeled_stmt = @label_stmt | @case;
@decl_stmt = @var_decl_stmt | @const_decl_stmt;
@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
@cond_stmt = @if_stmt | @switch_stmt;
@ -983,6 +986,7 @@ case @expr.kind of
| 116 = @property_pattern_expr
| 117 = @positional_pattern_expr
| 118 = @switch_case_expr
| 119 = @assign_coalesce_expr
;
@switch = @switch_stmt | @switch_expr;
@ -995,7 +999,7 @@ case @expr.kind of
| @string_literal_expr | @null_literal_expr;
@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr;
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
@assign_event_expr = @add_event_expr | @remove_event_expr;
@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr

Просмотреть файл

@ -360,10 +360,14 @@
<v>1854</v>
</e>
<e>
<k>@using_stmt</k>
<k>@using_block_stmt</k>
<v>5815</v>
</e>
<e>
<k>@using_decl_stmt</k>
<v>1000</v>
</e>
<e>
<k>@var_decl_stmt</k>
<v>243866</v>
</e>
@ -688,6 +692,10 @@
<v>116</v>
</e>
<e>
<k>@assign_coalesce_expr</k>
<v>116</v>
</e>
<e>
<k>@object_init_expr</k>
<v>5320</v>
</e>

Просмотреть файл

@ -104,6 +104,7 @@
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:132:13:132:13 | x | read |
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:132:13:132:13 | x | write |
| Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | s | write |
| Assignables.cs:138:19:138:19 | access to local variable x | Assignables.cs:138:19:138:19 | x | write |
| Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:5:30:5:30 | x | write |
| Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | z | write |
| Discards.cs:25:27:25:30 | access to parameter args | Discards.cs:23:27:23:30 | args | read |

Просмотреть файл

@ -87,6 +87,7 @@
| Assignables.cs:132:13:132:13 | x | Assignables.cs:132:13:132:17 | Int32 x = ... | Assignables.cs:132:13:132:13 | access to local variable x | Assignables.cs:132:17:132:17 | 0 | certain |
| Assignables.cs:132:13:132:13 | x | Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:15:133:15 | <none> | certain |
| Assignables.cs:133:29:133:29 | s | Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | <none> | certain |
| Assignables.cs:138:19:138:19 | x | Assignables.cs:138:19:138:50 | MemoryStream x = ... | Assignables.cs:138:19:138:19 | access to local variable x | Assignables.cs:138:23:138:50 | object creation of type MemoryStream | certain |
| Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | <none> | Discards.cs:5:30:5:30 | <none> | certain |
| Discards.cs:5:30:5:30 | x | Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:7:13:7:17 | false | certain |
| Discards.cs:19:14:19:14 | x | Discards.cs:19:9:19:29 | ... = ... | Discards.cs:19:9:19:29 | <none> | Discards.cs:19:9:19:29 | <none> | certain |

Просмотреть файл

@ -86,6 +86,7 @@
| Assignables.cs:132:13:132:17 | Int32 x = ... | Assignables.cs:132:13:132:17 | Int32 x = ... |
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:9:133:30 | delegate call |
| Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:9:133:30 | delegate call |
| Assignables.cs:138:19:138:50 | MemoryStream x = ... | Assignables.cs:138:19:138:50 | MemoryStream x = ... |
| Discards.cs:5:30:5:30 | x | Discards.cs:5:19:5:19 | enter f |
| Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:17 | ... = ... |
| Discards.cs:13:9:13:20 | ... = ... | Discards.cs:13:9:13:20 | ... = ... |

Просмотреть файл

@ -132,4 +132,11 @@ class Assignables
var x = 0;
d(ref x, out string s);
}
void UsingDeclarations()
{
using var x = new System.IO.MemoryStream();
}
}
// semmle-extractor-options: /langversion:8.0

Просмотреть файл

@ -95,6 +95,7 @@
| Assignables.cs:130:31:130:31 | d |
| Assignables.cs:132:13:132:13 | x |
| Assignables.cs:133:29:133:29 | s |
| Assignables.cs:138:19:138:19 | x |
| Discards.cs:5:6:5:8 | Item1 |
| Discards.cs:5:11:5:16 | Item2 |
| Discards.cs:5:30:5:30 | x |

Просмотреть файл

@ -37,6 +37,7 @@
| Assignables.cs:125:13:125:13 | s | Assignables.cs:125:17:125:25 | nameof(...) |
| Assignables.cs:125:13:125:13 | s | Assignables.cs:126:13:126:30 | nameof(...) |
| Assignables.cs:132:13:132:13 | x | Assignables.cs:132:17:132:17 | 0 |
| Assignables.cs:138:19:138:19 | x | Assignables.cs:138:23:138:50 | object creation of type MemoryStream |
| Discards.cs:5:30:5:30 | x | Discards.cs:7:13:7:17 | false |
| Finally.cs:7:13:7:13 | i | Finally.cs:7:17:7:17 | 0 |
| Finally.cs:7:13:7:13 | i | Finally.cs:15:17:15:17 | 1 |

Просмотреть файл

@ -0,0 +1,10 @@
using System;
class NullCoalescingAssignment
{
void NullCoalescing()
{
object o = null;
o ??= this;
}
}

Просмотреть файл

@ -0,0 +1,4 @@
nullcoalescing
| NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... |
assignments
| NullCoalescingAssignment.cs:8:9:8:18 | ... ??= ... | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... |

Просмотреть файл

@ -0,0 +1,7 @@
import csharp
query predicate nullcoalescing(NullCoalescingExpr expr) { any() }
query predicate assignments(AssignCoalesceExpr expr, Expr expanded) {
expanded = expr.getExpandedAssignment()
}

Просмотреть файл

@ -0,0 +1,11 @@
| NullCoalescingAssignment.cs:5:10:5:23 | enter NullCoalescing | NullCoalescingAssignment.cs:6:5:9:5 | {...} | semmle.label | successor |
| NullCoalescingAssignment.cs:6:5:9:5 | {...} | NullCoalescingAssignment.cs:7:9:7:24 | ... ...; | semmle.label | successor |
| NullCoalescingAssignment.cs:7:9:7:24 | ... ...; | NullCoalescingAssignment.cs:7:20:7:23 | null | semmle.label | successor |
| NullCoalescingAssignment.cs:7:16:7:23 | Object o = ... | NullCoalescingAssignment.cs:8:9:8:19 | ...; | semmle.label | successor |
| NullCoalescingAssignment.cs:7:20:7:23 | null | NullCoalescingAssignment.cs:7:16:7:23 | Object o = ... | semmle.label | successor |
| NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | semmle.label | non-null |
| NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | NullCoalescingAssignment.cs:8:15:8:18 | this access | semmle.label | null |
| NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | NullCoalescingAssignment.cs:5:10:5:23 | exit NullCoalescing | semmle.label | successor |
| NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... | NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | semmle.label | successor |
| NullCoalescingAssignment.cs:8:9:8:19 | ...; | NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... | semmle.label | successor |
| NullCoalescingAssignment.cs:8:15:8:18 | this access | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | semmle.label | successor |

Просмотреть файл

@ -0,0 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlow::Node node1, ControlFlow::Node node2, string label, string value) {
label = "semmle.label" and
exists(ControlFlow::SuccessorType t |
node2 = node1.getASuccessorByType(t) and value = t.toString()
)
and node1.getEnclosingCallable().hasName("NullCoalescing")
}

Просмотреть файл

@ -1,10 +0,0 @@
using System;
class StaticLocalFunction
{
int F()
{
static int G(int x) => x;
return G(12);
}
}

Просмотреть файл

@ -0,0 +1,13 @@
// semmle-extractor-options: /langversion:8.0
using System;
class StaticLocalFunctions
{
int Fn(int x)
{
static int I(int y) => y;
int J(int y) => x+y;
return I(x) + J(x);
}
}

Просмотреть файл

@ -0,0 +1 @@
| StaticLocalFunctions.cs:9:9:9:33 | I | static |

Просмотреть файл

@ -0,0 +1,5 @@
import csharp
from LocalFunction fn, string modifier
where fn.hasModifier(modifier)
select fn, modifier

Просмотреть файл

@ -0,0 +1,26 @@
| UsingDeclarations.cs:6:10:6:30 | enter TestUsingDeclarations | UsingDeclarations.cs:7:5:16:5 | {...} | semmle.label | successor |
| UsingDeclarations.cs:7:5:16:5 | {...} | UsingDeclarations.cs:8:9:8:116 | using ... ...; | semmle.label | successor |
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:49:8:53 | "..." | semmle.label | successor |
| UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... | UsingDeclarations.cs:8:95:8:99 | "..." | semmle.label | successor |
| UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... | semmle.label | successor |
| UsingDeclarations.cs:8:49:8:53 | "..." | UsingDeclarations.cs:8:56:8:68 | access to constant Open | semmle.label | successor |
| UsingDeclarations.cs:8:56:8:68 | access to constant Open | UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream | semmle.label | successor |
| UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... | UsingDeclarations.cs:10:9:12:9 | using (...) {...} | semmle.label | successor |
| UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... | semmle.label | successor |
| UsingDeclarations.cs:8:95:8:99 | "..." | UsingDeclarations.cs:8:102:8:114 | access to constant Open | semmle.label | successor |
| UsingDeclarations.cs:8:102:8:114 | access to constant Open | UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream | semmle.label | successor |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:49:10:53 | "..." | semmle.label | successor |
| UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... | UsingDeclarations.cs:10:95:10:99 | "..." | semmle.label | successor |
| UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream | UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... | semmle.label | successor |
| UsingDeclarations.cs:10:49:10:53 | "..." | UsingDeclarations.cs:10:56:10:68 | access to constant Open | semmle.label | successor |
| UsingDeclarations.cs:10:56:10:68 | access to constant Open | UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream | semmle.label | successor |
| UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... | UsingDeclarations.cs:11:9:12:9 | {...} | semmle.label | successor |
| UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream | UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... | semmle.label | successor |
| UsingDeclarations.cs:10:95:10:99 | "..." | UsingDeclarations.cs:10:102:10:114 | access to constant Open | semmle.label | successor |
| UsingDeclarations.cs:10:102:10:114 | access to constant Open | UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream | semmle.label | successor |
| UsingDeclarations.cs:11:9:12:9 | {...} | UsingDeclarations.cs:14:9:15:13 | using (...) {...} | semmle.label | successor |
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} | UsingDeclarations.cs:14:30:14:34 | "..." | semmle.label | successor |
| UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream | UsingDeclarations.cs:15:13:15:13 | ; | semmle.label | successor |
| UsingDeclarations.cs:14:30:14:34 | "..." | UsingDeclarations.cs:14:37:14:49 | access to constant Open | semmle.label | successor |
| UsingDeclarations.cs:14:37:14:49 | access to constant Open | UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream | semmle.label | successor |
| UsingDeclarations.cs:15:13:15:13 | ; | UsingDeclarations.cs:6:10:6:30 | exit TestUsingDeclarations | semmle.label | successor |

Просмотреть файл

@ -0,0 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlow::Node node1, ControlFlow::Node node2, string label, string value) {
label = "semmle.label" and
exists(ControlFlow::SuccessorType t |
node2 = node1.getASuccessorByType(t) and value = t.toString()
)
and node1.getEnclosingCallable().hasName("TestUsingDeclarations")
}

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.IO;
class UsingDeclarations
{
void TestUsingDeclarations()
{
using FileStream file1 = new FileStream("...", FileMode.Open), file2 = new FileStream("...", FileMode.Open);
using(FileStream file3 = new FileStream("...", FileMode.Open), file4 = new FileStream("...", FileMode.Open))
{
}
using(new FileStream("...", FileMode.Open))
;
}
}

Просмотреть файл

@ -0,0 +1,26 @@
localVars
| UsingDeclarations.cs:8:26:8:30 | file1 |
| UsingDeclarations.cs:8:72:8:76 | file2 |
| UsingDeclarations.cs:10:26:10:30 | file3 |
| UsingDeclarations.cs:10:72:10:76 | file4 |
localVariableDeclarations
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
usingStmts1
| UsingDeclarations.cs:8:9:8:116 | using ... ...; |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} |
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} |
usingStmts
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | 0 | UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | 1 | UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... |
usingDecls
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
usingExprs
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream |
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream |
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream |
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} | UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream |

Просмотреть файл

@ -0,0 +1,22 @@
import csharp
query predicate localVars(LocalVariable decl) {
decl.getEnclosingCallable().hasName("TestUsingDeclarations")
}
query predicate localVariableDeclarations(
LocalVariableDeclStmt stmt, int i, LocalVariableDeclExpr decl
) {
decl.getEnclosingCallable().hasName("TestUsingDeclarations") and
decl = stmt.getVariableDeclExpr(i)
}
query predicate usingStmts1(UsingStmt stmt) { any() }
query predicate usingStmts(UsingStmt stmt, int i, LocalVariableDeclExpr decl) {
decl = stmt.getVariableDeclExpr(i)
}
query predicate usingDecls(UsingDeclStmt stmt, int i, Expr e) { e = stmt.getChild(i) }
query predicate usingExprs(UsingStmt stmt, Expr e) { e = stmt.getAnExpr() }

Просмотреть файл

@ -5,7 +5,7 @@
import csharp
where
forall(UsingStmt s |
forall(UsingBlockStmt s |
exists(s.getAnExpr()) and
exists(s.getBody())
)

Просмотреть файл

@ -58,6 +58,10 @@ class Test
SqlConnection c1f = new SqlConnection();
Throw2(c1f);
c1f.Dispose();
// GOOD: using declaration
using SqlConnection c2 = new SqlConnection("");
c2.Open();
}
void Throw1(SqlConnection sc)
@ -71,3 +75,5 @@ class Test
return sc == null ? throw new Exception() : sc;
}
}
// semmle-extractor-options: /langversion:8.0

Просмотреть файл

@ -78,6 +78,9 @@ class Test
// GOOD: Passed to a library. This is only detected in CIL.
Console.SetOut(new StreamWriter("output.txt"));
// GOOD: Disposed automatically.
using var c2 = new Timer(TimerProc);
return null;
}
@ -88,3 +91,5 @@ class Test
{
}
}
// semmle-extractor-options: /langversion:8.0

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,2 @@
description: Support for null-coalescing assignment, static local functions, and using declarations.
compatibility: backwards

Просмотреть файл

@ -423,6 +423,14 @@ class SwitchCase extends Stmt, @case {
*/
SwitchExpr getSwitchExpr() { result.getACase() = this }
/**
* Gets the expression of the surrounding switch that this case is compared
* against.
*/
Expr getSelectorExpr() {
result = this.getSwitch().getExpr() or result = this.getSwitchExpr().getExpr()
}
/**
* PREVIEW FEATURE in Java 12. Subject to removal in a future release.
*
@ -625,7 +633,10 @@ class BreakStmt extends Stmt, @breakstmt {
override string pp() {
if this.hasLabel()
then result = "break " + this.getLabel()
else if this.hasValue() then result = "break ..." else result = "break"
else
if this.hasValue()
then result = "break ..."
else result = "break"
}
/** This statement's Halstead ID (used to compute Halstead metrics). */

Просмотреть файл

@ -93,7 +93,8 @@ class Guard extends ExprParent {
/** Gets the statement containing this guard. */
Stmt getEnclosingStmt() {
result = this.(Expr).getEnclosingStmt() or
result = this.(SwitchCase).getSwitch()
result = this.(SwitchCase).getSwitch() or
result = this.(SwitchCase).getSwitchExpr().getEnclosingStmt()
}
/**
@ -126,7 +127,7 @@ class Guard extends ExprParent {
branch = true and
bb2.getFirstNode() = sc.getControlFlowNode() and
pred = sc.getControlFlowNode().getAPredecessor() and
pred.(Expr).getParent*() = sc.getSwitch().getExpr() and
pred.(Expr).getParent*() = sc.getSelectorExpr() and
bb1 = pred.getBasicBlock()
)
or
@ -160,12 +161,12 @@ class Guard extends ExprParent {
}
private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
exists(BasicBlock caseblock, SwitchStmt ss |
ss.getACase() = sc and
exists(BasicBlock caseblock, Expr selector |
selector = sc.getSelectorExpr() and
caseblock.getFirstNode() = sc.getControlFlowNode() and
caseblock.bbDominates(bb) and
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
pred.(Expr).getParent*() = ss.getExpr()
pred.(Expr).getParent*() = selector
)
)
}
@ -254,7 +255,8 @@ private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
exists(ConstCase cc |
cc = g and
polarity = true and
cc.getSwitch().getExpr().getProperExpr() = e1 and
cc.getValue() = e2
cc.getSelectorExpr().getProperExpr() = e1 and
cc.getValue() = e2 and
strictcount(cc.getValue(_)) = 1
)
}

Просмотреть файл

@ -0,0 +1,9 @@
class Test {
void foo(String s) {
int x = switch(s) {
case "a", "b" -> 1;
case "c" -> 2;
default -> 3;
};
}
}

Просмотреть файл

@ -0,0 +1 @@
| Test.java:5:7:5:17 | stmt | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:7:5:17 | stmt |

Просмотреть файл

@ -0,0 +1,8 @@
import java
import semmle.code.java.controlflow.Guards
from Guard g, BasicBlock bb, boolean branch, VarAccess e1, Expr e2, boolean pol
where
g.controls(bb, branch) and
g.isEquality(e1, e2, pol)
select g, e1, e2, pol, branch, bb

Просмотреть файл

@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --enable-preview -source 12 -target 12

Просмотреть файл

@ -3,7 +3,7 @@
* @description Storing unencrypted passwords in configuration files is unsafe.
* @kind problem
* @problem.severity warning
* @precision high
* @precision medium
* @id js/password-in-configuration-file
* @tags security
* external/cwe/cwe-256
@ -12,6 +12,7 @@
*/
import javascript
import semmle.javascript.RestrictedLocations
/**
* Holds if some JSON or YAML file contains a property with name `key`
@ -45,7 +46,7 @@ predicate exclude(File f) {
f.getExtension().toLowerCase() = "raml"
}
from string key, string val, Locatable valElement
from string key, string val, Locatable valElement, string pwd
where
config(key, val, valElement) and
val != "" and
@ -53,13 +54,14 @@ where
not val.regexpMatch(Templating::getDelimiterMatchingRegexp()) and
(
key.toLowerCase() = "password" and
pwd = val and
// exclude interpolations of environment variables
not val.regexpMatch("\\$.*|%.*%")
or
key.toLowerCase() != "readme" and
// look for `password=...`, but exclude `password=;`, `password="$(...)"`,
// `password=%s` and `password==`
val.regexpMatch("(?is).*password\\s*=(?!\\s*;)(?!\"?[$`])(?!%s)(?!=).*")
pwd = val.regexpCapture("(?is).*password\\s*=\\s*(?!;|\"?[$`]|%s|=)(\\S+).*", 1)
) and
not exclude(valElement.getFile())
select valElement, "Avoid plaintext passwords in configuration files."
select (FirstLineOf)valElement, "Hard-coded password '" + pwd + "' in configuration file."

Просмотреть файл

@ -3,6 +3,7 @@
* @description Only keep results in non-framework code
* @kind treemap
* @id js/not-framework-file-metric-filter
* @metricType file
*/
import FilterFrameworks

Просмотреть файл

@ -5,6 +5,7 @@
* mapping comment.
* @kind treemap
* @id js/not-generated-file-metric-filter
* @metricType file
*/
import semmle.javascript.GeneratedCode

Просмотреть файл

@ -3,6 +3,7 @@
* @description Only keep results from files that are not minified.
* @kind treemap
* @id js/not-minified-file-metric-filter
* @metricType file
*/
import javascript

Просмотреть файл

@ -37,6 +37,6 @@ module Templating {
* storing it in its first (and only) capture group.
*/
string getDelimiterMatchingRegexp() {
result = ".*(" + concat("\\Q" + getADelimiter() + "\\E", "|") + ").*"
result = "(?s).*(" + concat("\\Q" + getADelimiter() + "\\E", "|") + ").*"
}
}

Просмотреть файл

@ -1,2 +1,3 @@
| mysql-config.json:4:16:4:23 | "secret" | Avoid plaintext passwords in configuration files. |
| tst4.json:2:10:2:38 | "script ... ecret'" | Avoid plaintext passwords in configuration files. |
| mysql-config.json:4:16:4:23 | "secret" | Hard-coded password 'secret' in configuration file. |
| tst4.json:2:10:2:38 | "script ... ecret'" | Hard-coded password ''secret'' in configuration file. |
| tst7.yml:2:9:2:6 | \| | Hard-coded password 'abc' in configuration file. |

Просмотреть файл

@ -1 +1,7 @@
password: $$SOME_VAR
config: |
[mail]
host = smtp.mydomain.com
port = 25
username = sample_admin@mydomain.com
password = abc

Просмотреть файл

@ -0,0 +1,6 @@
config: |
[mail]
host = smtp.mydomain.com
port = 25
username = {{username}}
password = {{pwd}}

Просмотреть файл

@ -57,15 +57,37 @@ predicate ok_to_fail(ImportExpr ie) {
os_specific_import(ie) != get_os()
}
class VersionTest extends @py_flow_node {
VersionTest() {
exists(string name |
name.matches("%version%") and
this.(CompareNode).getAChild+().pointsTo(Module::named("sys").attr(name))
)
}
string toString() {
result = "VersionTest"
}
}
/** A guard on the version of the Python interpreter */
class VersionGuard extends ConditionBlock {
VersionGuard() {
this.getLastNode() instanceof VersionTest
}
}
from ImportExpr ie
where not ie.refersTo(_) and
exists(Context c | c.appliesTo(ie.getAFlowNode())) and
not ok_to_fail(ie) and
not exists(VersionGuard guard |
if guard.isTrue() then
guard.controls(ie.getAFlowNode().getBasicBlock(), false)
else
guard.controls(ie.getAFlowNode().getBasicBlock(), true)
guard.controls(ie.getAFlowNode().getBasicBlock(), _)
)
select ie, "Unable to resolve import of '" + ie.getImportedModuleName() + "'."