Merge branch 'main' into aliasperf2

This commit is contained in:
Jeroen Ketema
2024-10-21 16:40:01 +02:00
committed by GitHub
543 changed files with 76384 additions and 55642 deletions

2
Cargo.lock generated
View File

@@ -390,11 +390,13 @@ dependencies = [
"ra_ap_base_db",
"ra_ap_hir",
"ra_ap_hir_def",
"ra_ap_hir_expand",
"ra_ap_ide_db",
"ra_ap_load-cargo",
"ra_ap_parser",
"ra_ap_paths",
"ra_ap_project_model",
"ra_ap_span",
"ra_ap_syntax",
"ra_ap_vfs",
"rust-extractor-macros",

View File

@@ -23,7 +23,7 @@ bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1")
bazel_dep(name = "gazelle", version = "0.38.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")

View File

@@ -0,0 +1,17 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprRequirement(Expr expr) {
exists(int kind | exprs(expr, kind, _) | kind = [391, 392, 393])
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprRequirement(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
class Parameter extends @parameter {
string toString() { none() }
}
class ParameterizedElement extends @parameterized_element {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
from Parameter param, ParameterizedElement pe, int index, Type type
where
params(param, pe, index, type) and
not pe instanceof @requires_expr
select param, pe, index, type

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
description: Support C++20 requires expressions
compatibility: partial
compound_requirement_is_noexcept.rel: delete
exprs.rel: run exprs.qlo
params.rel: run params.qlo

View File

@@ -1,3 +1,10 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.
## 2.0.1
No user-facing changes.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.

View File

@@ -0,0 +1,6 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.0.1
lastReleaseVersion: 2.0.2

View File

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

View File

@@ -6,9 +6,156 @@ import semmle.code.cpp.exprs.Expr
/**
* A C++ requires expression.
*
* For example, with `T` and `U` template parameters:
* ```cpp
* requires (T x, U y) { x + y; };
* ```
*/
class RequiresExpr extends Expr, @requires_expr {
override string toString() { result = "requires ..." }
override string toString() {
if exists(this.getAParameter())
then result = "requires(...) { ... }"
else result = "requires { ... }"
}
override string getAPrimaryQlClass() { result = "RequiresExpr" }
/**
* Gets a requirement in this requires expression.
*/
RequirementExpr getARequirement() { result = this.getAChild() }
/**
* Gets the nth requirement in this requires expression.
*/
RequirementExpr getRequirement(int n) { result = this.getChild(n) }
/**
* Gets the number of requirements in this requires expression.
*/
int getNumberOfRequirements() { result = count(this.getARequirement()) }
/**
* Gets a parameter of this requires expression, if any.
*/
Parameter getAParameter() { result.getRequiresExpr() = underlyingElement(this) }
/**
* Gets the the nth parameter of this requires expression.
*/
Parameter getParameter(int n) {
result.getRequiresExpr() = underlyingElement(this) and result.getIndex() = n
}
/**
* Gets the number of parameters of this requires expression.
*/
int getNumberOfParameters() { result = count(this.getAParameter()) }
}
/**
* A C++ requirement in a requires expression.
*/
class RequirementExpr extends Expr { }
/**
* A C++ simple requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x, U y) { x + y; };
* ```
* with `T` and `U` template parameters, then `x + y;` is a simple requirement.
*/
class SimpleRequirementExpr extends RequirementExpr {
SimpleRequirementExpr() {
this.getParent() instanceof RequiresExpr and
not this instanceof TypeRequirementExpr and
not this instanceof CompoundRequirementExpr and
not this instanceof NestedRequirementExpr
}
override string getAPrimaryQlClass() { result = "SimpleRequirementExpr" }
}
/**
* A C++ type requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { typename T::a_field; };
* ```
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
*/
class TypeRequirementExpr extends RequirementExpr, TypeName {
TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
}
/**
* A C++ compound requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x) { { x } noexcept -> std::same_as<int>; };
* ```
* with `T` a template parameter, then `{ x } noexcept -> std::same_as<int>;` is
* a compound requirement.
*/
class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
override string toString() {
if exists(this.getReturnTypeRequirement())
then result = "{ ... } -> ..."
else result = "{ ... }"
}
override string getAPrimaryQlClass() { result = "CompoundRequirementExpr" }
/**
* Gets the expression from the compound requirement.
*/
Expr getExpr() { result = this.getChild(0) }
/**
* Gets the return type requirement from the compound requirement, if any.
*/
Expr getReturnTypeRequirement() { result = this.getChild(1) }
/**
* Holds if the expression from the compound requirement must not be
* potentially throwing.
*/
predicate isNoExcept() { compound_requirement_is_noexcept(underlyingElement(this)) }
}
/**
* A C++ nested requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { requires std::is_same<T, int>::value; };
* ```
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
* a nested requirement.
*/
class NestedRequirementExpr extends Expr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
/**
* Gets the constraint from the nested requirement.
*/
Expr getConstraint() { result = this.getChild(0) }
}
/**
* A C++ concept id expression.
*/
class ConceptIdExpr extends RequirementExpr, @concept_id {
override string toString() { result = "concept<...>" }
override string getAPrimaryQlClass() { result = "ConceptIdExpr" }
}

View File

@@ -129,7 +129,7 @@ class Element extends ElementBase {
* or certain kinds of `Statement`.
*/
Element getParentScope() {
// result instanceof class
// result instanceof Class
exists(Declaration m |
m = this and
result = m.getDeclaringType() and
@@ -138,31 +138,40 @@ class Element extends ElementBase {
or
exists(TemplateClass tc | this = tc.getATemplateArgument() and result = tc)
or
// result instanceof namespace
// result instanceof Namespace
exists(Namespace n | result = n and n.getADeclaration() = this)
or
exists(FriendDecl d, Namespace n | this = d and n.getADeclaration() = d and result = n)
or
exists(Namespace n | this = n and result = n.getParentNamespace())
or
// result instanceof stmt
// result instanceof Stmt
exists(LocalVariable v |
this = v and
exists(DeclStmt ds | ds.getADeclaration() = v and result = ds.getParent())
)
or
exists(Parameter p | this = p and result = p.getFunction())
exists(Parameter p |
this = p and
(
result = p.getFunction() or
result = p.getCatchBlock().getParent().(Handler).getParent().(TryStmt).getParent() or
result = p.getRequiresExpr().getEnclosingStmt().getParent()
)
)
or
exists(GlobalVariable g, Namespace n | this = g and n.getADeclaration() = g and result = n)
or
exists(TemplateVariable tv | this = tv.getATemplateArgument() and result = tv)
or
exists(EnumConstant e | this = e and result = e.getDeclaringEnum())
or
// result instanceof block|function
// result instanceof Block|Function
exists(BlockStmt b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
or
exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf)
or
// result instanceof stmt
// result instanceof Stmt
exists(ControlStructure s | this = s and result = s.getParent())
or
using_container(unresolveElement(result), underlyingElement(this))

View File

@@ -7,8 +7,8 @@ import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ function parameter or catch block parameter. For example the
* function parameter `p` and the catch block parameter `e` in the following
* A C/C++ function parameter, catch block parameter, or requires expression parameter.
* For example the function parameter `p` and the catch block parameter `e` in the following
* code:
* ```
* void myFunction(int p) {
@@ -20,8 +20,8 @@ private import semmle.code.cpp.internal.ResolveClass
* }
* ```
*
* For catch block parameters, there is a one-to-one correspondence between
* the `Parameter` and its `ParameterDeclarationEntry`.
* For catch block parameters and expression , there is a one-to-one
* correspondence between the `Parameter` and its `VariableDeclarationEntry`.
*
* For function parameters, there is a one-to-many relationship between
* `Parameter` and `ParameterDeclarationEntry`, because one function can
@@ -73,7 +73,8 @@ class Parameter extends LocalScopeVariable, @parameter {
}
private VariableDeclarationEntry getANamedDeclarationEntry() {
result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
result = this.getAnEffectiveDeclarationEntry() and
exists(string name | var_decls(unresolveElement(result), _, _, name, _) | name != "")
}
/**
@@ -118,6 +119,12 @@ class Parameter extends LocalScopeVariable, @parameter {
*/
BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the requires expression to which the parameter belongs, if it is a
* requires expression parameter.
*/
RequiresExpr getRequiresExpr() { params(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the zero-based index of this parameter.
*

View File

@@ -80,6 +80,10 @@ private Declaration getAnEnclosingDeclaration(Locatable ast) {
or
result = ast.(Parameter).getFunction()
or
result = ast.(Parameter).getCatchBlock().getEnclosingFunction()
or
result = ast.(Parameter).getRequiresExpr().getEnclosingFunction()
or
result = ast.(Expr).getEnclosingDeclaration()
or
result = ast.(Initializer).getDeclaration()
@@ -99,7 +103,10 @@ private newtype TPrintAstNode =
stmt.getADeclarationEntry() = entry and
shouldPrintDeclaration(stmt.getEnclosingFunction())
} or
TParametersNode(Function func) { shouldPrintDeclaration(func) } or
TFunctionParametersNode(Function func) { shouldPrintDeclaration(func) } or
TRequiresExprParametersNode(RequiresExpr req) {
shouldPrintDeclaration(getAnEnclosingDeclaration(req))
} or
TConstructorInitializersNode(Constructor ctor) {
ctor.hasEntryPoint() and
shouldPrintDeclaration(ctor)
@@ -303,14 +310,14 @@ class ExprNode extends AstNode {
ExprNode() { expr = ast }
override AstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex)
override PrintAstNode getChildInternal(int childIndex) {
result.(AstNode).getAst() = expr.getChild(childIndex)
or
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
result.(AstNode).getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
or
exists(int destructorIndex |
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
result.(AstNode).getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
)
}
@@ -329,7 +336,8 @@ class ExprNode extends AstNode {
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
result =
getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).(AstNode).getAst())
}
/**
@@ -409,6 +417,26 @@ class StmtExprNode extends ExprNode {
}
}
/**
* A node representing a `RequiresExpr`
*/
class RequiresExprNode extends ExprNode {
override RequiresExpr expr;
override PrintAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.(RequiresExprParametersNode).getRequiresExpr() = expr
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = super.getChildAccessorPredicateInternal(childIndex)
or
childIndex = -1 and result = "<params>"
}
}
/**
* A node representing a `DeclarationEntry`.
*/
@@ -510,6 +538,22 @@ class DeclStmtNode extends StmtNode {
}
}
/**
* A node representing a `Handler`.
*/
class HandlerNode extends ChildStmtNode {
Handler handler;
HandlerNode() { handler = stmt }
override BaseAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.getAst() = handler.getParameter()
}
}
/**
* A node representing a `Parameter`.
*/
@@ -552,10 +596,10 @@ class InitializerNode extends AstNode {
/**
* A node representing the parameters of a `Function`.
*/
class ParametersNode extends PrintAstNode, TParametersNode {
class FunctionParametersNode extends PrintAstNode, TFunctionParametersNode {
Function func;
ParametersNode() { this = TParametersNode(func) }
FunctionParametersNode() { this = TFunctionParametersNode(func) }
final override string toString() { result = "" }
@@ -576,6 +620,33 @@ class ParametersNode extends PrintAstNode, TParametersNode {
final Function getFunction() { result = func }
}
/**
* A node representing the parameters of a `RequiresExpr`.
*/
class RequiresExprParametersNode extends PrintAstNode, TRequiresExprParametersNode {
RequiresExpr req;
RequiresExprParametersNode() { this = TRequiresExprParametersNode(req) }
final override string toString() { result = "" }
final override Location getLocation() { result = getRepresentativeLocation(req) }
override AstNode getChildInternal(int childIndex) {
result.getAst() = req.getParameter(childIndex)
}
override string getChildAccessorPredicateInternal(int childIndex) {
exists(this.getChildInternal(childIndex)) and
result = "getParameter(" + childIndex.toString() + ")"
}
/**
* Gets the `RequiresExpr` for which this node represents the parameters.
*/
final RequiresExpr getRequiresExpr() { result = req }
}
/**
* A node representing the initializer list of a `Constructor`.
*/
@@ -679,7 +750,7 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
override PrintAstNode getChildInternal(int childIndex) {
childIndex = 0 and
result.(ParametersNode).getFunction() = func
result.(FunctionParametersNode).getFunction() = func
or
childIndex = 1 and
result.(ConstructorInitializersNode).getConstructor() = func
@@ -754,6 +825,8 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
or
s.(Handler).getParameter() = e and pred = "getParameter()"
or
s.(IfStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(IfStmt).getCondition() = e and pred = "getCondition()"
@@ -901,6 +974,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
or
expr.(CompoundRequirementExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(CompoundRequirementExpr).getReturnTypeRequirement() = ele and
pred = "getReturnTypeRequirement()"
or
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
or
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
@@ -921,6 +999,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
or
expr.(NestedRequirementExpr).getConstraint() = ele and pred = "getConstraint()"
or
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
@@ -960,6 +1040,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
or
exists(int n |
expr.(RequiresExpr).getRequirement(n) = ele and
pred = "getRequirement(" + n + ")"
)
or
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"

View File

@@ -241,6 +241,10 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
name != "" and result = name
or
name = "" and result = this.getVariable().(LocalVariable).getName()
or
name = "" and
not this instanceof ParameterDeclarationEntry and
result = this.getVariable().(Parameter).getName()
)
)
}
@@ -295,19 +299,11 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
private string getAnonymousParameterDescription() {
not exists(this.getName()) and
exists(string idx |
idx =
((this.getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")
.replaceAll("11st", "11th")
.replaceAll("12nd", "12th")
.replaceAll("13rd", "13th") and
exists(string anon |
anon = "(unnamed parameter " + this.getIndex().toString() + ")" and
if exists(this.getCanonicalName())
then
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter"
then result = "declaration of " + this.getCanonicalName() + " as " + anon
else result = "declaration of " + anon
)
}

View File

@@ -181,12 +181,7 @@ class VariableDeclarationEntry extends @var_decl {
string getName() { var_decls(this, _, _, result, _) and result != "" }
}
class Parameter extends LocalScopeVariable, @parameter {
@functionorblock function;
int index;
Parameter() { params(this, function, index, _) }
}
class Parameter extends LocalScopeVariable, @parameter { }
class GlobalOrNamespaceVariable extends Variable, @globalvariable { }

View File

@@ -1328,7 +1328,10 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() and
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() or
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
) and
exists(kind)
}

View File

@@ -17,6 +17,7 @@ private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
private import DataFlowDispatch as DataFlowDispatch
import ExprNodes
/**
@@ -2497,3 +2498,16 @@ class AdditionalCallTarget extends Unit {
*/
abstract Declaration viableTarget(Call call);
}
/**
* Gets a function that may be called by `call`.
*
* Note that `call` may be a call to a function pointer expression.
*/
Function getARuntimeTarget(Call call) {
exists(DataFlowCall dfCall | dfCall.asCallInstruction().getUnconvertedResultExpression() = call |
result = DataFlowDispatch::viableCallable(dfCall).asSourceCallable()
or
result = DataFlowImplCommon::viableCallableLambda(dfCall, _).asSourceCallable()
)
}

View File

@@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/** The function `fopen` and friends. */
private class Fopen extends Function, AliasFunction, SideEffectFunction {
private class Fopen extends Function, AliasFunction, SideEffectFunction, TaintFunction {
Fopen() {
this.hasGlobalOrStdName(["fopen", "fopen_s", "freopen"])
or
@@ -47,4 +47,22 @@ private class Fopen extends Function, AliasFunction, SideEffectFunction {
i = 0 and
buffer = true
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
(
this.hasGlobalOrStdName(["fopen", "freopen"]) or
this.hasGlobalName(["_wfopen", "_fsopen", "_wfsopen"])
) and
input.isParameterDeref(0) and
output.isReturnValueDeref()
or
// The out parameter is a pointer to a `FILE*`.
this.hasGlobalOrStdName("fopen_s") and
input.isParameterDeref(1) and
output.isParameterDeref(0, 2)
or
this.hasGlobalName(["_open", "_wopen"]) and
input.isParameterDeref(0) and
output.isReturnValue()
}
}

View File

@@ -534,7 +534,7 @@ static_asserts(
#keyset[function, index, type_id]
params(
int id: @parameter,
int function: @functionorblock ref,
int function: @parameterized_element ref,
int index: int ref,
int type_id: @type ref
);
@@ -1791,6 +1791,9 @@ case @expr.kind of
| 388 = @datasizeof
| 389 = @c11_generic
| 390 = @requires_expr
| 391 = @nested_requirement
| 392 = @compound_requirement
| 393 = @concept_id
;
@var_args_expr = @vastartexpr
@@ -1909,6 +1912,10 @@ case @expr.kind of
| @istriviallyrelocatable
;
compound_requirement_is_noexcept(
int expr: @compound_requirement ref
);
new_allocated_type(
unique int expr: @new_expr ref,
int type_id: @type ref
@@ -2168,11 +2175,11 @@ stmt_decl_entry_bind(
int decl_entry: @element ref
);
@functionorblock = @function | @stmt_block;
@parameterized_element = @function | @stmt_block | @requires_expr;
blockscope(
unique int block: @stmt_block ref,
int enclosing: @functionorblock ref
int enclosing: @parameterized_element ref
);
@jump = @stmt_goto | @stmt_break | @stmt_continue;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Support C++20 requires expressions
compatibility: backwards

View File

@@ -1,3 +1,12 @@
## 1.2.5
### Minor Analysis Improvements
* The `cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives and increase true positives.
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.
## 1.2.4
### Minor Analysis Improvements

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives increase true positives.

View File

@@ -0,0 +1,8 @@
## 1.2.5
### Minor Analysis Improvements
* The `cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives and increase true positives.
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.4
lastReleaseVersion: 1.2.5

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.2.5-dev
version: 1.2.6-dev
groups:
- cpp
- queries

View File

@@ -870,6 +870,8 @@ Throw.cpp:
# 8| Type = [BoolType] bool
# 8| ValueCategory = prvalue
# 12| getChild(1): [Handler] <handler>
# 12| getParameter(): [Parameter] e
# 12| Type = [PointerType] E *
# 12| getBlock(): [CatchBlock] { ... }
# 13| getStmt(0): [ExprStmt] ExprStmt
# 13| getExpr(): [ReThrowExpr] re-throw exception

View File

@@ -3,6 +3,9 @@ uniqueEnclosingCallable
| test.cpp:864:47:864:54 | call to source | Node should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Node should have one enclosing callable but has 0. |
| test.cpp:872:53:872:56 | 1 | Node should have one enclosing callable but has 0. |
| test.cpp:1126:33:1129:1 | {...} | Node should have one enclosing callable but has 0. |
| test.cpp:1127:3:1127:13 | reads_input | Node should have one enclosing callable but has 0. |
| test.cpp:1128:3:1128:21 | not_does_read_input | Node should have one enclosing callable but has 0. |
uniqueCallEnclosingCallable
| test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. |

View File

@@ -323,6 +323,7 @@ irFlow
| test.cpp:1069:9:1069:14 | call to source | test.cpp:1074:10:1074:10 | i |
| test.cpp:1069:9:1069:14 | call to source | test.cpp:1081:10:1081:10 | i |
| test.cpp:1117:27:1117:34 | call to source | test.cpp:1117:27:1117:34 | call to source |
| test.cpp:1132:11:1132:16 | call to source | test.cpp:1121:8:1121:8 | x |
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |

View File

@@ -1115,4 +1115,20 @@ void indirect_sink_const_ref(const T&);
void test_temp_with_conversion_from_materialization() {
indirect_sink_const_ref(source()); // $ ir MISSING: ast
}
void reads_input(int x) {
sink(x); // $ ir MISSING: ast
}
void not_does_read_input(int x);
void (*dispatch_table[])(int) = {
reads_input,
not_does_read_input
};
void test_dispatch_table(int i) {
int x = source();
dispatch_table[i](x);
}

View File

@@ -6584,6 +6584,16 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| taint.cpp:767:21:767:24 | ref arg path | taint.cpp:768:8:768:11 | path | |
| taint.cpp:768:8:768:11 | path | taint.cpp:768:7:768:11 | * ... | |
| taint.cpp:778:37:778:42 | call to source | taint.cpp:779:7:779:9 | obj | |
| taint.cpp:785:23:785:28 | source | taint.cpp:785:23:785:28 | source | |
| taint.cpp:785:23:785:28 | source | taint.cpp:786:18:786:23 | source | |
| taint.cpp:785:23:785:28 | source | taint.cpp:790:15:790:20 | source | |
| taint.cpp:786:12:786:16 | call to fopen | taint.cpp:787:7:787:7 | f | |
| taint.cpp:786:18:786:23 | source | taint.cpp:786:12:786:16 | call to fopen | TAINT |
| taint.cpp:789:8:789:9 | f2 | taint.cpp:790:11:790:12 | f2 | |
| taint.cpp:789:8:789:9 | f2 | taint.cpp:791:7:791:8 | f2 | |
| taint.cpp:790:10:790:12 | ref arg & ... | taint.cpp:790:11:790:12 | f2 [inner post update] | |
| taint.cpp:790:10:790:12 | ref arg & ... | taint.cpp:791:7:791:8 | f2 | |
| taint.cpp:790:11:790:12 | f2 | taint.cpp:790:10:790:12 | & ... | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -777,4 +777,16 @@ TaintInheritingContentObject source(bool);
void test_TaintInheritingContent() {
TaintInheritingContentObject obj = source(true);
sink(obj.flowFromObject); // $ ir MISSING: ast
}
FILE* fopen(const char*, const char*);
int fopen_s(FILE** pFile, const char *filename, const char *mode);
void fopen_test(char* source) {
FILE* f = fopen(source, "r");
sink(f); // $ ast,ir
FILE* f2;
fopen_s(&f2, source, "r");
sink(f2); // $ ast,ir
}

View File

@@ -25,8 +25,8 @@
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
| declarationEntry.cpp:39:7:39:13 | definition of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes |
| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes |
| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes |

View File

@@ -1,7 +1,7 @@
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) |
| file://:0:0:0:0 | definition of fp_offset |
| file://:0:0:0:0 | definition of gp_offset |
| file://:0:0:0:0 | definition of overflow_arg_area |

View File

@@ -9055,6 +9055,8 @@ ir.cpp:
# 733| Value = [Literal] 7
# 733| ValueCategory = prvalue
# 735| getChild(1): [Handler] <handler>
# 735| getParameter(): [Parameter] s
# 735| Type = [PointerType] const char *
# 735| getBlock(): [CatchBlock] { ... }
# 736| getStmt(0): [ExprStmt] ExprStmt
# 736| getExpr(): [ThrowExpr] throw ...
@@ -9067,6 +9069,8 @@ ir.cpp:
# 736| Type = [PointerType] const char *
# 736| ValueCategory = prvalue(load)
# 738| getChild(2): [Handler] <handler>
# 738| getParameter(): [Parameter] e
# 738| Type = [LValueReferenceType] const String &
# 738| getBlock(): [CatchBlock] { ... }
# 740| getChild(3): [Handler] <handler>
# 740| getBlock(): [CatchAnyBlock] { ... }
@@ -12852,6 +12856,8 @@ ir.cpp:
# 1200| Value = [Literal] 7
# 1200| ValueCategory = prvalue
# 1202| getChild(1): [Handler] <handler>
# 1202| getParameter(): [Parameter] s
# 1202| Type = [PointerType] const char *
# 1202| getBlock(): [CatchBlock] { ... }
# 1203| getStmt(0): [ExprStmt] ExprStmt
# 1203| getExpr(): [ThrowExpr] throw ...
@@ -12864,6 +12870,8 @@ ir.cpp:
# 1203| Type = [PointerType] const char *
# 1203| ValueCategory = prvalue(load)
# 1205| getChild(2): [Handler] <handler>
# 1205| getParameter(): [Parameter] e
# 1205| Type = [LValueReferenceType] const String &
# 1205| getBlock(): [CatchBlock] { ... }
# 1207| getStmt(1): [ReturnStmt] return ...
# 1211| [TopLevelFunction] void VectorTypes(int)
@@ -20586,6 +20594,8 @@ ir.cpp:
# 2281| Type = [Struct] String
# 2281| ValueCategory = lvalue
# 2282| getChild(1): [Handler] <handler>
# 2282| getParameter(): [Parameter] s
# 2282| Type = [PointerType] const char *
# 2282| getBlock(): [CatchBlock] { ... }
# 2283| getStmt(0): [ExprStmt] ExprStmt
# 2283| getExpr(): [ThrowExpr] throw ...
@@ -20598,6 +20608,8 @@ ir.cpp:
# 2283| Type = [PointerType] const char *
# 2283| ValueCategory = prvalue(load)
# 2285| getChild(2): [Handler] <handler>
# 2285| getParameter(): [Parameter] e
# 2285| Type = [LValueReferenceType] const String &
# 2285| getBlock(): [CatchBlock] { ... }
# 2287| getChild(3): [Handler] <handler>
# 2287| getBlock(): [CatchAnyBlock] { ... }
@@ -22845,6 +22857,8 @@ ir.cpp:
# 2537| Value = [Literal] 42
# 2537| ValueCategory = prvalue
# 2539| getChild(1): [Handler] <handler>
# 2539| getParameter(): [Parameter] (unnamed parameter 0)
# 2539| Type = [PlainCharType] char
# 2539| getBlock(): [CatchBlock] { ... }
# 2541| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
# 2541| Type = [VoidType] void
@@ -23571,10 +23585,26 @@ ir.cpp:
# 2692| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 2692| Type = [IntType] int
# 2692| getVariable().getInitializer(): [Initializer] initializer for y
#-----| getExpr(): [RequiresExpr] requires ...
#-----| getExpr(): [RequiresExpr] requires { ... }
#-----| Type = [BoolType] bool
#-----| Value = [RequiresExpr] 1
#-----| ValueCategory = prvalue
#-----| <params>:
# 2692| getRequirement(0): [GTExpr,SimpleRequirementExpr] ... > ...
# 2692| Type = [BoolType] bool
# 2692| ValueCategory = prvalue
# 2692| getGreaterOperand(): [SizeofTypeOperator] sizeof(int)
# 2692| Type = [LongType] unsigned long
# 2692| Value = [SizeofTypeOperator] 4
# 2692| ValueCategory = prvalue
# 2692| getLesserOperand(): [Literal] 0
# 2692| Type = [IntType] int
# 2692| Value = [Literal] 0
# 2692| ValueCategory = prvalue
# 2692| getLesserOperand().getFullyConverted(): [CStyleCast] (unsigned long)...
# 2692| Conversion = [IntegralConversion] integral conversion
# 2692| Type = [LongType] unsigned long
# 2692| ValueCategory = prvalue
#-----| getExpr().getFullyConverted(): [CStyleCast] (int)...
#-----| Conversion = [IntegralConversion] integral conversion
#-----| Type = [IntType] int

View File

@@ -1,11 +1,11 @@
| test.c:2:8:2:10 | declaration of 1st parameter |
| test.c:2:13:2:15 | declaration of 2nd parameter |
| test.c:2:18:2:20 | declaration of 3rd parameter |
| test.c:2:23:2:25 | declaration of 4th parameter |
| test.c:3:8:3:10 | declaration of y1 as anonymous 1st parameter |
| test.c:3:13:3:15 | declaration of y2 as anonymous 2nd parameter |
| test.c:3:18:3:20 | declaration of y3 as anonymous 3rd parameter |
| test.c:3:23:3:25 | declaration of y4 as anonymous 4th parameter |
| test.c:2:8:2:10 | declaration of (unnamed parameter 0) |
| test.c:2:13:2:15 | declaration of (unnamed parameter 1) |
| test.c:2:18:2:20 | declaration of (unnamed parameter 2) |
| test.c:2:23:2:25 | declaration of (unnamed parameter 3) |
| test.c:3:8:3:10 | declaration of y1 as (unnamed parameter 0) |
| test.c:3:13:3:15 | declaration of y2 as (unnamed parameter 1) |
| test.c:3:18:3:20 | declaration of y3 as (unnamed parameter 2) |
| test.c:3:23:3:25 | declaration of y4 as (unnamed parameter 3) |
| test.c:4:12:4:13 | declaration of x1 |
| test.c:4:20:4:21 | declaration of x2 |
| test.c:4:28:4:29 | declaration of x3 |

View File

@@ -14,6 +14,13 @@ namespace foo {
}
}
template<typename T>
T var = 42;
int g() {
requires(int l) { l; };
return var<int>;
}
// semmle-extractor-options: -std=c++20

View File

@@ -1,5 +1,8 @@
| 0 | file://:0:0:0:0 | (global namespace) | file://:0:0:0:0 | __va_list_tag |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:2:11:2:13 | foo |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:18:3:18:3 | var |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:18:7:18:7 | var |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:20:5:20:5 | g |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | fp_offset |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | gp_offset |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | operator= |
@@ -14,7 +17,11 @@
| 1 | parents.cpp:4:10:4:10 | f | parents.cpp:4:19:13:5 | { ... } |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:5:11:5:11 | j |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:6:11:10:7 | { ... } |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:11:18:11:18 | e |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:11:21:12:7 | { ... } |
| 1 | parents.cpp:6:11:10:7 | { ... } | parents.cpp:7:9:9:9 | for(...;...;...) ... |
| 1 | parents.cpp:6:11:10:7 | { ... } | parents.cpp:7:33:9:9 | { ... } |
| 1 | parents.cpp:7:33:9:9 | { ... } | parents.cpp:8:15:8:15 | k |
| 1 | parents.cpp:18:7:18:7 | var | parents.cpp:17:19:17:19 | T |
| 1 | parents.cpp:20:5:20:5 | g | parents.cpp:20:9:24:1 | { ... } |
| 1 | parents.cpp:20:9:24:1 | { ... } | parents.cpp:21:16:21:16 | l |

View File

@@ -1,5 +1,5 @@
| file://:0:0:0:0 | declaration of 1st parameter | LibB/libb_internal.h:5:8:5:12 | thing |
| file://:0:0:0:0 | declaration of 1st parameter | LibB/libb_internal.h:5:8:5:12 | thing |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | LibB/libb_internal.h:5:8:5:12 | thing |
| file://:0:0:0:0 | declaration of (unnamed parameter 0) | LibB/libb_internal.h:5:8:5:12 | thing |
| include.h:3:25:3:33 | num | LibD/libd.h:5:12:5:14 | num |
| main.cpp:8:31:8:31 | call to container | LibC/libc.h:9:3:9:3 | container |
| main.cpp:8:31:8:31 | definition of x | LibB/libb_internal.h:5:8:5:12 | thing |

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.26
lastReleaseVersion: 1.7.27

View File

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

View File

@@ -1,3 +1,7 @@
## 1.7.27
No user-facing changes.
## 1.7.26
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.26
lastReleaseVersion: 1.7.27

View File

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

View File

@@ -1,3 +1,7 @@
## 3.0.1
No user-facing changes.
## 3.0.0
### Breaking Changes

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 3.0.0
lastReleaseVersion: 3.0.1

View File

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

View File

@@ -1,3 +1,7 @@
## 1.0.10
No user-facing changes.
## 1.0.9
### Minor Analysis Improvements

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.9
lastReleaseVersion: 1.0.10

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 1.0.10-dev
version: 1.0.11-dev
groups:
- csharp
- queries

View File

@@ -101,7 +101,7 @@
latest version of CodeQL...</div>
</div>
<div class="Subhead border-0">
<a href="codeql-overview/supported-languages-and-frameworks/">
<a href="../codeql-query-help/codeql-cwe-coverage/">
<div class="Subhead-heading f4 text-center">CodeQL coverage of CWEs</div>
</a>
<div class="Subhead-description">Detailed information on the coverage of Common Weakness Enumerations (CWEs) in the latest release...</div>

View File

@@ -22,7 +22,7 @@
Eclipse compiler for Java (ECJ) [6]_",``.java``
Kotlin,"Kotlin 1.5.0 to 2.1.0\ *x*","kotlinc",``.kt``
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [7]_"
Python [8]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12",Not applicable,``.py``
Python [8]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [9]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
Swift [10]_,"Swift 5.4-5.10","Swift compiler","``.swift``"
TypeScript [11]_,"2.6-5.6",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"

View File

@@ -518,6 +518,7 @@ func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label {
// For more information on objects, see:
// https://github.com/golang/example/blob/master/gotypes/README.md#objects
func extractObject(tw *trap.Writer, obj types.Object, lbl trap.Label) {
checkObjectNotSpecialized(obj)
name := obj.Name()
isBuiltin := obj.Parent() == types.Universe
var kind int
@@ -1607,7 +1608,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
case *types.Struct:
kind = dbscheme.StructType.Index()
for i := 0; i < tp.NumFields(); i++ {
field := tp.Field(i)
field := tp.Field(i).Origin()
// ensure the field is associated with a label - note that
// struct fields do not have a parent scope, so they are not
@@ -1637,7 +1638,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
// Note that methods coming from embedded interfaces can be
// accessed through `Method(i)`, so there is no need to
// deal with them separately.
meth := tp.Method(i)
meth := tp.Method(i).Origin()
// Note that methods do not have a parent scope, so they are
// not dealt with by `extractScopes`
@@ -1707,7 +1708,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
// ensure all methods have labels - note that methods do not have a
// parent scope, so they are not dealt with by `extractScopes`
for i := 0; i < origintp.NumMethods(); i++ {
meth := origintp.Method(i)
meth := origintp.Method(i).Origin()
extractMethod(tw, meth)
}
@@ -1715,7 +1716,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
// associate all methods of underlying interface with this type
if underlyingInterface, ok := underlying.(*types.Interface); ok {
for i := 0; i < underlyingInterface.NumMethods(); i++ {
methlbl := extractMethod(tw, underlyingInterface.Method(i))
methlbl := extractMethod(tw, underlyingInterface.Method(i).Origin())
dbscheme.MethodHostsTable.Emit(tw, methlbl, lbl)
}
}
@@ -1787,7 +1788,7 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
case *types.Interface:
var b strings.Builder
for i := 0; i < tp.NumMethods(); i++ {
meth := tp.Method(i)
meth := tp.Method(i).Origin()
methLbl := extractType(tw, meth.Type())
if i > 0 {
b.WriteString(",")
@@ -2143,3 +2144,20 @@ func skipExtractingValueForLeftOperand(tw *trap.Writer, be *ast.BinaryExpr) bool
}
return true
}
// checkObjectNotSpecialized exits the program if `obj` is specialized. Note
// that specialization is only possible for function objects and variable
// objects.
func checkObjectNotSpecialized(obj types.Object) {
if funcObj, ok := obj.(*types.Func); ok && funcObj != funcObj.Origin() {
log.Fatalf("Encountered unexpected specialization %s of generic function object %s", funcObj.FullName(), funcObj.Origin().FullName())
}
if varObj, ok := obj.(*types.Var); ok && varObj != varObj.Origin() {
log.Fatalf("Encountered unexpected specialization %s of generic variable object %s", varObj.String(), varObj.Origin().String())
}
if typeNameObj, ok := obj.(*types.TypeName); ok {
if namedType, ok := typeNameObj.Type().(*types.Named); ok && namedType != namedType.Origin() {
log.Fatalf("Encountered type object for specialization %s of named type %s", namedType.String(), namedType.Origin().String())
}
}
}

View File

@@ -1,3 +1,7 @@
## 1.0.10
No user-facing changes.
## 1.0.9
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.9
lastReleaseVersion: 1.0.10

View File

@@ -1,5 +1,5 @@
name: codeql-go-consistency-queries
version: 1.0.10-dev
version: 1.0.11-dev
groups:
- go
- queries

View File

@@ -1,3 +1,11 @@
## 2.1.1
### Minor Analysis Improvements
* Added member predicates `StructTag.hasOwnFieldWithTag` and `Field.getTag`, which enable CodeQL queries to examine struct field tags.
* Added member predicate `InterfaceType.hasPrivateMethodWithQualifiedName`, which enables CodeQL queries to distinguish interfaces with matching non-exported method names that are declared in different packages, and are therefore incompatible.
* Local source models with the `stdin` source kind have been added for the variable `os.Stdin` and the functions `fmt.Scan`, `fmt.Scanf` and `fmt.Scanln`. You can optionally include threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see [Analyzing your code with CodeQL queries](https://docs.github.com/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries#including-model-packs-to-add-potential-sources-of-tainted-data>) and [Customizing your advanced setup for code scanning](https://docs.github.com/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models).
## 2.1.0
### Deprecated APIs

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* Added member predicates `StructTag.hasOwnFieldWithTag` and `Field.getTag`, which enable CodeQL queries to examine struct field tags.
* Added member predicate `InterfaceType.hasPrivateMethodWithQualifiedName`, which enables CodeQL queries to distinguish interfaces with matching non-exported method names that are declared in different packages, and are therefore incompatible.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The AST viewer now shows type parameter declarations in the correct place in the AST.

View File

@@ -0,0 +1,7 @@
## 2.1.1
### Minor Analysis Improvements
* Added member predicates `StructTag.hasOwnFieldWithTag` and `Field.getTag`, which enable CodeQL queries to examine struct field tags.
* Added member predicate `InterfaceType.hasPrivateMethodWithQualifiedName`, which enables CodeQL queries to distinguish interfaces with matching non-exported method names that are declared in different packages, and are therefore incompatible.
* Local source models with the `stdin` source kind have been added for the variable `os.Stdin` and the functions `fmt.Scan`, `fmt.Scanf` and `fmt.Scanln`. You can optionally include threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see [Analyzing your code with CodeQL queries](https://docs.github.com/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries#including-model-packs-to-add-potential-sources-of-tainted-data>) and [Customizing your advanced setup for code scanning](https://docs.github.com/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models).

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.1.0
lastReleaseVersion: 2.1.1

View File

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

View File

@@ -55,6 +55,8 @@ class AstNode extends @node, Locatable {
kind = "commentgroup" and result = this.(File).getCommentGroup(i)
or
kind = "comment" and result = this.(CommentGroup).getComment(i)
or
kind = "typeparamdecl" and result = this.(TypeParamDeclParent).getTypeParameterDecl(i)
}
/**

View File

@@ -212,10 +212,7 @@ class MethodDecl extends FuncDecl {
*
* is `Rectangle`.
*/
NamedType getReceiverBaseType() {
result = this.getReceiverType() or
result = this.getReceiverType().(PointerType).getBaseType()
}
NamedType getReceiverBaseType() { result = lookThroughPointerType(this.getReceiverType()) }
/**
* Gets the receiver variable of this method.

View File

@@ -519,13 +519,7 @@ class Method extends Function {
* Gets the receiver base type of this method, that is, either the base type of the receiver type
* if it is a pointer type, or the receiver type itself if it is not a pointer type.
*/
Type getReceiverBaseType() {
exists(Type recv | recv = this.getReceiverType() |
if recv instanceof PointerType
then result = recv.(PointerType).getBaseType()
else result = recv
)
}
Type getReceiverBaseType() { result = lookThroughPointerType(this.getReceiverType()) }
/** Holds if this method has name `m` and belongs to the method set of type `tp` or `*tp`. */
private predicate isIn(NamedType tp, string m) {

View File

@@ -446,11 +446,7 @@ class StructType extends @structtype, CompositeType {
if n = ""
then (
isEmbedded = true and
(
name = tp.(NamedType).getName()
or
name = tp.(PointerType).getBaseType().(NamedType).getName()
)
name = lookThroughPointerType(tp).(NamedType).getName()
) else (
isEmbedded = false and
name = n
@@ -518,9 +514,7 @@ class StructType extends @structtype, CompositeType {
this.hasFieldCand(_, embeddedParent, depth - 1, true) and
result.getName() = name and
(
result.getReceiverBaseType() = embeddedParent.getType()
or
result.getReceiverBaseType() = embeddedParent.getType().(PointerType).getBaseType()
result.getReceiverBaseType() = lookThroughPointerType(embeddedParent.getType())
or
methodhosts(result, embeddedParent.getType())
)
@@ -644,6 +638,16 @@ class PointerType extends @pointertype, CompositeType {
override string toString() { result = "pointer type" }
}
/**
* Gets the base type if `t` is a pointer type, otherwise `t` itself.
*/
Type lookThroughPointerType(Type t) {
not t instanceof PointerType and
result = t
or
result = t.(PointerType).getBaseType()
}
private newtype TTypeSetTerm =
MkTypeSetTerm(TypeSetLiteralType tslit, int index) { component_types(tslit, index, _, _) }

View File

@@ -358,11 +358,7 @@ module IR {
override predicate reads(ValueEntity v) { v = field }
override Type getResultType() {
if field.getType() instanceof PointerType
then result = field.getType().(PointerType).getBaseType()
else result = field.getType()
}
override Type getResultType() { result = lookThroughPointerType(field.getType()) }
override ControlFlow::Root getRoot() { result.isRootOf(e) }

View File

@@ -727,7 +727,10 @@ module Public {
override string getNodeKind() { result = "external parameter node" }
override Type getType() {
result = this.getSummarizedCallable().getType().getParameterType(this.getPos())
result =
this.getSummarizedCallable()
.getType()
.getParameterType(pragma[only_bind_into](this.getPos()))
or
this.getPos() = -1 and
result = this.getSummarizedCallable().asFunction().(Method).getReceiverType()

View File

@@ -112,6 +112,15 @@ module Fmt {
Scanner() { this.hasQualifiedName("fmt", ["Scan", "Scanf", "Scanln"]) }
}
private class ScannerSource extends SourceNode {
ScannerSource() {
// All of the arguments which are sources are varargs.
this.asExpr() = any(Scanner s).getACall().getAnImplicitVarargsArgument().asExpr()
}
override string getThreatModel() { result = "stdin" }
}
/**
* The `Fscan` function or one of its variants,
* all of which read from a specified `io.Reader`.

View File

@@ -43,4 +43,12 @@ module Os {
input = inp and output = outp
}
}
private class Stdin extends SourceNode {
Stdin() {
exists(Variable osStdin | osStdin.hasQualifiedName("os", "Stdin") | this = osStdin.getARead())
}
override string getThreatModel() { result = "stdin" }
}
}

View File

@@ -1,3 +1,7 @@
## 1.1.1
No user-facing changes.
## 1.1.0
### Query Metadata Changes

View File

@@ -73,7 +73,7 @@ predicate isRegexpMethodCall(DataFlow::MethodCallNode c) {
exists(NamedType regexp, Type recvtp |
regexp.getName() = "Regexp" and recvtp = c.getReceiver().getType()
|
recvtp = regexp or recvtp.(PointerType).getBaseType() = regexp
lookThroughPointerType(recvtp) = regexp
)
}

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.0
lastReleaseVersion: 1.1.1

View File

@@ -1,5 +1,5 @@
name: codeql/go-queries
version: 1.1.1-dev
version: 1.1.2-dev
groups:
- go
- queries

View File

@@ -639,6 +639,11 @@ other.go:
# 11| Type = int
# 11| 0: [Ident, VariableName] myNested
# 11| Type = func() int
# 8| 3: [TypeParamDecl] type parameter declaration
# 8| 0: [Ident, TypeName] int
# 8| Type = int
# 8| 1: [Ident, TypeName] U
# 8| Type = U
# 15| 5: [VarDecl] variable declaration
# 15| 0: [ValueSpec] value declaration specifier
# 15| 0: [Ident, VariableName] x
@@ -648,3 +653,32 @@ other.go:
# 15| 2: [IntLit] 0
# 15| Type = int
# 15| Value = [IntLit] 0
# 17| 6: [TypeDecl] type declaration
# 17| 0: [TypeSpec] type declaration specifier
# 17| 0: [Ident, TypeName] myType
# 17| Type = myType
# 17| 1: [ArrayTypeExpr] array type
# 17| Type = []T
# 17| 0: [Ident, TypeName] T
# 17| Type = T
# 17| 2: [TypeParamDecl] type parameter declaration
# 17| 0: [TypeSetLiteralExpr] type set literal
# 17| Type = ~string
# 17| 0: [Ident, TypeName] string
# 17| Type = string
# 17| 1: [Ident, TypeName] T
# 17| Type = T
# 19| 7: [MethodDecl] function declaration
# 19| 0: [FunctionName, Ident] f
# 19| Type = func()
# 19| 1: [FuncTypeExpr] function type
# 19| 2: [ReceiverDecl] receiver declaration
# 19| 0: [GenericTypeInstantiationExpr] generic type instantiation expression
# 19| Type = myType
# 19| 0: [Ident, TypeName] myType
# 19| Type = myType
# 19| 1: [Ident, TypeName] U
# 19| Type = U
# 19| 1: [Ident, VariableName] m
# 19| Type = myType
# 19| 3: [BlockStmt] block statement

View File

@@ -619,6 +619,11 @@ other.go:
# 11| Type = int
# 11| 0: [Ident, VariableName] myNested
# 11| Type = func() int
# 8| 3: [TypeParamDecl] type parameter declaration
# 8| 0: [Ident, TypeName] int
# 8| Type = int
# 8| 1: [Ident, TypeName] U
# 8| Type = U
# 15| 5: [VarDecl] variable declaration
# 15| 0: [ValueSpec] value declaration specifier
# 15| 0: [Ident, VariableName] x
@@ -628,3 +633,32 @@ other.go:
# 15| 2: [IntLit] 0
# 15| Type = int
# 15| Value = [IntLit] 0
# 17| 6: [TypeDecl] type declaration
# 17| 0: [TypeSpec] type declaration specifier
# 17| 0: [Ident, TypeName] myType
# 17| Type = myType
# 17| 1: [ArrayTypeExpr] array type
# 17| Type = []T
# 17| 0: [Ident, TypeName] T
# 17| Type = T
# 17| 2: [TypeParamDecl] type parameter declaration
# 17| 0: [TypeSetLiteralExpr] type set literal
# 17| Type = ~string
# 17| 0: [Ident, TypeName] string
# 17| Type = string
# 17| 1: [Ident, TypeName] T
# 17| Type = T
# 19| 7: [MethodDecl] function declaration
# 19| 0: [FunctionName, Ident] f
# 19| Type = func()
# 19| 1: [FuncTypeExpr] function type
# 19| 2: [ReceiverDecl] receiver declaration
# 19| 0: [GenericTypeInstantiationExpr] generic type instantiation expression
# 19| Type = myType
# 19| 0: [Ident, TypeName] myType
# 19| Type = myType
# 19| 1: [Ident, TypeName] U
# 19| Type = U
# 19| 1: [Ident, VariableName] m
# 19| Type = myType
# 19| 3: [BlockStmt] block statement

View File

@@ -56,6 +56,11 @@ other.go:
# 11| Type = int
# 11| 0: [Ident, VariableName] myNested
# 11| Type = func() int
# 8| 3: [TypeParamDecl] type parameter declaration
# 8| 0: [Ident, TypeName] int
# 8| Type = int
# 8| 1: [Ident, TypeName] U
# 8| Type = U
# 15| 2: [VarDecl] variable declaration
# 15| 0: [ValueSpec] value declaration specifier
# 15| 0: [Ident, VariableName] x
@@ -65,3 +70,18 @@ other.go:
# 15| 2: [IntLit] 0
# 15| Type = int
# 15| Value = [IntLit] 0
# 17| 3: [TypeDecl] type declaration
# 17| 0: [TypeSpec] type declaration specifier
# 17| 0: [Ident, TypeName] myType
# 17| Type = myType
# 17| 1: [ArrayTypeExpr] array type
# 17| Type = []T
# 17| 0: [Ident, TypeName] T
# 17| Type = T
# 17| 2: [TypeParamDecl] type parameter declaration
# 17| 0: [TypeSetLiteralExpr] type set literal
# 17| Type = ~string
# 17| 0: [Ident, TypeName] string
# 17| Type = string
# 17| 1: [Ident, TypeName] T
# 17| Type = T

View File

@@ -41,6 +41,11 @@ other.go:
# 11| Type = int
# 11| 0: [Ident, VariableName] myNested
# 11| Type = func() int
# 8| 3: [TypeParamDecl] type parameter declaration
# 8| 0: [Ident, TypeName] int
# 8| Type = int
# 8| 1: [Ident, TypeName] U
# 8| Type = U
# 15| 5: [VarDecl] variable declaration
# 15| 0: [ValueSpec] value declaration specifier
# 15| 0: [Ident, VariableName] x
@@ -50,3 +55,32 @@ other.go:
# 15| 2: [IntLit] 0
# 15| Type = int
# 15| Value = [IntLit] 0
# 17| 6: [TypeDecl] type declaration
# 17| 0: [TypeSpec] type declaration specifier
# 17| 0: [Ident, TypeName] myType
# 17| Type = myType
# 17| 1: [ArrayTypeExpr] array type
# 17| Type = []T
# 17| 0: [Ident, TypeName] T
# 17| Type = T
# 17| 2: [TypeParamDecl] type parameter declaration
# 17| 0: [TypeSetLiteralExpr] type set literal
# 17| Type = ~string
# 17| 0: [Ident, TypeName] string
# 17| Type = string
# 17| 1: [Ident, TypeName] T
# 17| Type = T
# 19| 7: [MethodDecl] function declaration
# 19| 0: [FunctionName, Ident] f
# 19| Type = func()
# 19| 1: [FuncTypeExpr] function type
# 19| 2: [ReceiverDecl] receiver declaration
# 19| 0: [GenericTypeInstantiationExpr] generic type instantiation expression
# 19| Type = myType
# 19| 0: [Ident, TypeName] myType
# 19| Type = myType
# 19| 1: [Ident, TypeName] U
# 19| Type = U
# 19| 1: [Ident, VariableName] m
# 19| Type = myType
# 19| 3: [BlockStmt] block statement

View File

@@ -1,3 +1,9 @@
other.go:
# 8| [TypeParamDecl] type parameter declaration
# 8| 0: [Ident, TypeName] int
# 8| Type = int
# 8| 1: [Ident, TypeName] U
# 8| Type = U
go.mod:
# 0| [GoModFile] go.mod
# 1| 0: [GoModModuleLine] go.mod module line
@@ -45,3 +51,18 @@ other.go:
# 15| 2: [IntLit] 0
# 15| Type = int
# 15| Value = [IntLit] 0
# 17| 3: [TypeDecl] type declaration
# 17| 0: [TypeSpec] type declaration specifier
# 17| 0: [Ident, TypeName] myType
# 17| Type = myType
# 17| 1: [ArrayTypeExpr] array type
# 17| Type = []T
# 17| 0: [Ident, TypeName] T
# 17| Type = T
# 17| 2: [TypeParamDecl] type parameter declaration
# 17| 0: [TypeSetLiteralExpr] type set literal
# 17| Type = ~string
# 17| 0: [Ident, TypeName] string
# 17| Type = string
# 17| 1: [Ident, TypeName] T
# 17| Type = T

View File

@@ -1,4 +1,3 @@
module codeql-go-tests/printast
go 1.14
go 1.18

View File

@@ -5,7 +5,7 @@ func main() {}
func f() {}
func g() {}
func hasNested() {
func hasNested[U int]() {
myNested := func() int { return 1 }
myNested()
@@ -13,3 +13,7 @@ func hasNested() {
}
var x int = 0
type myType[T ~string] []T
func (m myType[U]) f() {}

View File

@@ -0,0 +1,3 @@
module test
go 1.22.6

View File

@@ -0,0 +1,3 @@
testFailures
invalidModelRow
failures

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