Compare commits

..

1 Commits

Author SHA1 Message Date
Florin Coada
4cf5d4178f Changelogx fix for 2.18.0 c/cpp breaking changes 2024-07-29 10:11:26 +01:00
3169 changed files with 29734 additions and 195614 deletions

View File

@@ -24,6 +24,5 @@ common --registry=file:///%workspace%/misc/bazel/registry
common --registry=https://bcr.bazel.build
common --@rules_dotnet//dotnet/settings:strict_deps=false
common --experimental_isolated_extension_usages
try-import %workspace%/local.bazelrc

View File

@@ -8,4 +8,3 @@ common --registry=https://bcr.bazel.build
# its implementation packages without providing any code itself.
# We either can depend on internal implementation details, or turn of strict deps.
common --@rules_dotnet//dotnet/settings:strict_deps=false
common --experimental_isolated_extension_usages

View File

@@ -1 +1 @@
5f5d70b6c4d2fb1a889479569107f1692239e8a7
7.2.1

View File

@@ -24,5 +24,5 @@ jobs:
extra_args: >
buildifier --all-files 2>&1 ||
(
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel/buildifier"; exit 1
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
)

View File

@@ -37,7 +37,7 @@ jobs:
with:
languages: cpp
config-file: ./.github/codeql/codeql-config.yml
- name: "[Ubuntu] Remove GCC 13 from runner image"
shell: bash
run: |
@@ -48,7 +48,7 @@ jobs:
- name: "Build Swift extractor using Bazel"
run: |
bazel clean --expunge
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
bazel shutdown
- name: Perform CodeQL Analysis

View File

@@ -76,7 +76,7 @@ jobs:
needs: measure
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: measurements
path: stats

View File

@@ -140,26 +140,25 @@ jobs:
path: |
${{ runner.temp }}/query-packs/*
retention-days: 1
include-hidden-files: true
package:
runs-on: ubuntu-latest
needs: [build, compile-queries]
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: ruby.dbscheme
path: ruby/ruby
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: extractor-ubuntu-latest
path: ruby/linux64
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: extractor-windows-latest
path: ruby/win64
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: extractor-macos-latest
path: ruby/osx64
@@ -177,8 +176,7 @@ jobs:
name: codeql-ruby-pack
path: ruby/codeql-ruby.zip
retention-days: 1
include-hidden-files: true
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: codeql-ruby-queries
path: ruby/qlpacks
@@ -195,7 +193,6 @@ jobs:
name: codeql-ruby-bundle
path: ruby/codeql-ruby-bundle.zip
retention-days: 1
include-hidden-files: true
test:
defaults:
@@ -214,7 +211,7 @@ jobs:
uses: ./.github/actions/fetch-codeql
- name: Download Ruby bundle
uses: actions/download-artifact@v4.1.7
uses: actions/download-artifact@v3
with:
name: codeql-ruby-bundle
path: ${{ runner.temp }}

View File

@@ -63,7 +63,7 @@ jobs:
needs: measure
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4.1.7
- uses: actions/download-artifact@v3
with:
name: measurements
path: stats

2
.gitignore vendored
View File

@@ -7,8 +7,8 @@
.cache
# qltest projects and artifacts
*.actual
*/ql/test/**/*.testproj
*/ql/test/**/*.actual
*/ql/test/**/go.sum
# Visual studio temporaries, except a file used by QL4VS

View File

@@ -26,7 +26,7 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //misc/bazel/buildifier
entry: bazel run //misc/bazel:buildifier
pass_filenames: false
# DISABLED: can be enabled by copying this config and installing `pre-commit` with `--config` on the copy

View File

@@ -1,7 +1,6 @@
module(
name = "ql",
name = "codeql",
version = "0.0",
repo_name = "codeql",
)
# this points to our internal repository when `codeql` is checked out as a submodule thereof
@@ -15,7 +14,7 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_go", version = "0.50.0")
bazel_dep(name = "rules_go", version = "0.48.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
bazel_dep(name = "rules_python", version = "0.32.2")
@@ -24,20 +23,18 @@ 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 = "gazelle", version = "0.38.0")
bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.49.1")
bazel_dep(name = "rules_rust", version = "0.46.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
# crate_py but shortened due to Windows file path considerations
cp = use_extension(
crate = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
isolate = True,
)
cp.from_cargo(
crate.from_cargo(
name = "py_deps",
cargo_lockfile = "//python/extractor/tsg-python:Cargo.lock",
manifests = [
@@ -45,23 +42,15 @@ cp.from_cargo(
"//python/extractor/tsg-python/tsp:Cargo.toml",
],
)
use_repo(cp, "py_deps")
# crate_ruby, but shortened due to windows file paths
r = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
isolate = True,
)
r.from_cargo(
name = "rd",
crate.from_cargo(
name = "ruby_deps",
cargo_lockfile = "//ruby/extractor:Cargo.lock",
manifests = [
"//ruby/extractor:Cargo.toml",
"//ruby/extractor/codeql-extractor-fake-crate:Cargo.toml",
],
)
use_repo(r, ruby_deps = "rd")
use_repo(crate, "py_deps", "ruby_deps")
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "8.0.101")

View File

@@ -1,17 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 385 <= kind and kind <= 388)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -1,14 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
from Expr expr, Type type, int kind
where
sizeof_bind(expr, type) and
exprs(expr, kind, _) and
(kind = 93 or kind = 94)
select expr, type

View File

@@ -1,4 +0,0 @@
description: Add new builtin operations
compatibility: partial
exprs.rel: run exprs.qlo
sizeof_bind.rel: run sizeof_bind.qlo

View File

@@ -1,32 +0,0 @@
/*
* Approach: replace conversion expressions of kind 389 (= @c11_generic) by
* conversion expressions of kind 12 (= @parexpr), i.e., a `ParenthesisExpr`,
* and drop the relation which its child expressions, which are just syntactic
* sugar. Parenthesis expressions are equally benign as C11 _Generic expressions,
* and behave similarly in the context of the IR.
*/
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location {
string toString() { none() }
}
class ExprParent extends @exprparent {
string toString() { none() }
}
query predicate new_exprs(Expr expr, int new_kind, Location loc) {
exists(int kind | exprs(expr, kind, loc) | if kind = 389 then new_kind = 12 else new_kind = kind)
}
query predicate new_exprparents(Expr expr, int index, ExprParent expr_parent) {
exprparents(expr, index, expr_parent) and
(
not expr_parent instanceof @expr
or
exists(int kind | exprs(expr_parent.(Expr), kind, _) | kind != 389)
)
}

View File

@@ -1,4 +0,0 @@
description: Expose C11 _Generics
compatibility: partial
exprs.rel: run downgrades.ql new_exprs
exprparents.rel: run downgrades.ql new_exprparents

View File

@@ -1,3 +0,0 @@
description: description: Support explicit(bool) specifiers
compatibility: full
explicit_specifier_exprs.rel: delete

View File

@@ -1,3 +0,0 @@
description: Add relation between deduction guides and class templates
compatibility: full
deduction_guide_for_class.rel: delete

View File

@@ -1,22 +1,3 @@
## 1.4.1
No user-facing changes.
## 1.4.0
### New Features
* A `getTemplateClass` predicate was added to the `DeductionGuide` class to get the class template for which the deduction guide is a guide.
* An `isExplicit` predicate was added to the `Function` class that determines whether the function was declared as explicit.
* A `getExplicitExpr` predicate was added to the `Function` class that yields the constant boolean expression (if any) that conditionally determines whether the function is explicit.
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
### Minor Analysis Improvements
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.
## 1.3.0
### New Features

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.

View File

@@ -1,5 +0,0 @@
---
category: feature
---
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
* Added a subclass of `Expr` for `__datasizeof` expressions.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added a class `C11GenericExpr` to represent C11 generic selection expressions. The generic selection is represented as a `Conversion` on the expression that will be selected.

View File

@@ -1,14 +0,0 @@
## 1.4.0
### New Features
* A `getTemplateClass` predicate was added to the `DeductionGuide` class to get the class template for which the deduction guide is a guide.
* An `isExplicit` predicate was added to the `Function` class that determines whether the function was declared as explicit.
* A `getExplicitExpr` predicate was added to the `Function` class that yields the constant boolean expression (if any) that conditionally determines whether the function is explicit.
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
### Minor Analysis Improvements
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.1
lastReleaseVersion: 1.3.0

View File

@@ -1,14 +0,0 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*1]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*2]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*3]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*4]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*5]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*6]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*7]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*8]", "ReturnValue", "taint", "manual"]

View File

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

View File

@@ -158,26 +158,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/
predicate isConsteval() { this.hasSpecifier("is_consteval") }
/**
* Holds if this function is declared to be `explicit`.
*/
predicate isExplicit() { this.hasSpecifier("explicit") }
/**
* Gets the constant expression that determines whether the function is explicit.
*
* For example, for the following code the result is the expression `sizeof(T) == 1`:
* ```
* template<typename T> struct C {
* explicit(sizeof(T) == 1)
* C(const T);
* };
* ```
*/
Expr getExplicitExpr() {
explicit_specifier_exprs(underlyingElement(this), unresolveElement(result))
}
/**
* Holds if this function is declared with `__attribute__((naked))` or
* `__declspec(naked)`.
@@ -918,11 +898,4 @@ class UserDefinedLiteral extends Function {
*/
class DeductionGuide extends Function {
DeductionGuide() { functions(underlyingElement(this), _, 8) }
/**
* Gets the class template for which this is a deduction guide.
*/
TemplateClass getTemplateClass() {
deduction_guide_for_class(underlyingElement(this), unresolveElement(result))
}
}

View File

@@ -385,21 +385,6 @@ class CastNode extends ConversionNode {
}
}
/**
* A node representing a `C11GenericExpr`.
*/
class C11GenericNode extends ConversionNode {
C11GenericExpr generic;
C11GenericNode() { generic = conv }
override AstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex - count(generic.getAChild()))
or
result.getAst() = generic.getChild(childIndex)
}
}
/**
* A node representing a `StmtExpr`.
*/
@@ -875,15 +860,6 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
or
expr.(C11GenericExpr).getControllingExpr() = ele and pred = "getControllingExpr()"
or
exists(int n |
expr.(C11GenericExpr).getAssociationType(n) = ele.(TypeName).getType() and
pred = "getAssociationType(" + n + ")"
or
expr.(C11GenericExpr).getAssociationExpr(n) = ele and pred = "getAssociationExpr(" + n + ")"
)
or
expr.(Call).getQualifier() = ele and pred = "getQualifier()"
or
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")

View File

@@ -435,17 +435,12 @@ private predicate elementSpec(
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunction(Function f) {
private Function getFullyTemplatedMemberFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and
(
exists(Class c, Class templateClass, int i |
c.isConstructedFrom(templateClass) and
f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
or
not exists(f.getDeclaringType()) and
f.isConstructedFrom(result)
exists(Class c, Class templateClass, int i |
c.isConstructedFrom(templateClass) and
f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
}
@@ -469,14 +464,14 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
*/
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction |
templateFunction = getFullyTemplatedFunction(f) and
templateFunction = getFullyTemplatedMemberFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
)
or
exists(string mid, TemplateParameter tp, Function templateFunction |
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
templateFunction = getFullyTemplatedFunction(f) and
templateFunction = getFullyTemplatedMemberFunction(f) and
tp = templateFunction.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
)
@@ -487,18 +482,12 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
* with `class:N` (where `N` is the index of the template).
*/
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
// If there is a declaring type then we start by expanding the function templates
exists(Class template |
f.getDeclaringType().isConstructedFrom(template) and
remaining = template.getNumberOfTemplateArguments() and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
)
or
// If there is no declaring type we're done after expanding the function templates
not exists(f.getDeclaringType()) and
remaining = 0 and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
or
exists(string mid, TemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
f.getDeclaringType().isConstructedFrom(template) and
@@ -581,6 +570,38 @@ private string getSignatureWithoutFunctionTemplateNames(
)
}
private string paramsStringPart(Function c, int i) {
not c.isFromUninstantiatedTemplate(_) and
(
i = -1 and result = "(" and exists(c)
or
exists(int n, string p | getParameterTypeName(c, n) = p |
i = 2 * n and result = p
or
i = 2 * n - 1 and result = "," and n != 0
)
or
i = 2 * c.getNumberOfParameters() and result = ")"
)
}
/**
* Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
*
* Returns the empty string if the callable has no parameters.
* Parameter types are represented by their type erasure.
*/
cached
private string paramsString(Function c) {
result = concat(int i | | paramsStringPart(c, i) order by i)
}
bindingset[func]
private predicate matchesSignature(Function func, string signature) {
signature = "" or
paramsString(func) = signature
}
/**
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
* - `typeArgs` represents the named template parameters supplied to `type`, and
@@ -729,17 +750,17 @@ private predicate elementSpecWithArguments0(
/**
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
* `func`'s signature matches `signature`.
* `method`'s signature matches `signature`.
*
* `signature` may contain template parameter names that are bound by `type` and `name`.
*/
pragma[nomagic]
private predicate elementSpecMatchesSignature(
Function func, string namespace, string type, boolean subtypes, string name, string signature
Function method, string namespace, string type, boolean subtypes, string name, string signature
) {
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
pragma[only_bind_into](signature), _) and
signatureMatches(func, signature, type, name, 0)
signatureMatches(method, signature, type, name, 0)
}
/**
@@ -755,22 +776,13 @@ private predicate hasClassAndName(Class classWithMethod, Function method, string
)
}
bindingset[name]
pragma[inline_late]
private predicate funcHasQualifiedName(Function func, string namespace, string name) {
exists(string nameWithoutArgs |
parseAngles(name, nameWithoutArgs, _, "") and
func.hasQualifiedName(namespace, nameWithoutArgs)
)
}
/**
* Holds if `namedClass` is in namespace `namespace` and has
* name `type` (excluding any template parameters).
*/
bindingset[type, namespace]
pragma[inline_late]
private predicate classHasQualifiedName(Class namedClass, string namespace, string type) {
private predicate hasQualifiedName(Class namedClass, string namespace, string type) {
exists(string typeWithoutArgs |
parseAngles(type, typeWithoutArgs, _, "") and
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
@@ -792,16 +804,15 @@ private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature
) {
(
// Non-member functions
elementSpec(namespace, type, subtypes, name, signature, _) and
subtypes = false and
type = "" and
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
funcHasQualifiedName(result, namespace, name)
// Non-member functions
exists(Function func |
func.hasQualifiedName(namespace, name) and
type = "" and
matchesSignature(func, signature) and
subtypes = false and
not exists(func.getDeclaringType()) and
result = func
)
or
// Member functions
@@ -814,7 +825,7 @@ private Element interpretElement0(
elementSpec(namespace, type, subtypes, name, "", _) and
hasClassAndName(classWithMethod, result, name)
) and
classHasQualifiedName(namedClass, namespace, type) and
hasQualifiedName(namedClass, namespace, type) and
(
// member declared in the named type or a subtype of it
subtypes = true and
@@ -953,3 +964,21 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
interpretSummary(this, _, _, _, provenance, _)
}
}
// adapter class for converting Mad neutrals to `NeutralCallable`s
private class NeutralCallableAdapter extends NeutralCallable {
string kind;
string provenance_;
NeutralCallableAdapter() {
// Neutral models have not been implemented for CPP.
none() and
exists(this) and
exists(kind) and
exists(provenance_)
}
override string getKind() { result = kind }
override predicate hasProvenance(Provenance provenance) { provenance = provenance_ }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -1885,59 +1885,3 @@ class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
}
/**
* A C++ `__is_trivially_equality_comparable` built-in operation.
*
* Returns `true` if comparing two objects of type `_Tp` is equivalent to
* comparing their object representations.
*
* ```
* template<typename _Tp>
* struct is_trivially_equality_comparable
* : public integral_constant<bool, __is_trivially_equality_comparable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyEqualityComparable extends BuiltInOperation,
@istriviallyequalitycomparable
{
override string toString() { result = "__is_trivially_equality_comparable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyEqualityComparable" }
}
/**
* A C++ `__is_scoped_enum` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a type is a scoped enum.
* ```
* template<typename _Tp>
* constexpr bool is_scoped_enum = __is_scoped_enum(_Tp);
* ```
*/
class BuiltInOperationIsScopedEnum extends BuiltInOperation, @isscopedenum {
override string toString() { result = "__is_scoped_enum" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsScopedEnum" }
}
/**
* A C++ `__is_trivially_relocatable` built-in operation.
*
* Returns `true` if moving an object of type `_Tp` is equivalent to
* copying the underlying bytes.
*
* ```
* template<typename _Tp>
* struct is_trivially_relocatable
* : public integral_constant<bool, __is_trivially_relocatable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyRelocatable extends BuiltInOperation, @istriviallyrelocatable {
override string toString() { result = "__is_trivially_relocatable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyRelocatable" }
}

View File

@@ -791,53 +791,6 @@ class AlignofTypeOperator extends AlignofOperator {
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C++ `__datasizeof` expression (used by some implementations
* of the `<type_traits>` header).
*
* The `__datasizeof` expression behaves identically to `sizeof` except
* that the result ignores tail padding.
*/
class DatasizeofOperator extends Expr, @datasizeof {
override int getPrecedence() { result = 16 }
}
/**
* A C++ `__datasizeof` expression whose operand is an expression.
*/
class DatasizeofExprOperator extends DatasizeofOperator {
DatasizeofExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "DatasizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "__datasizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
}
/**
* A C++ `__datasizeof` expression whose operand is a type name.
*/
class DatasizeofTypeOperator extends DatasizeofOperator {
DatasizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C/C++ array to pointer conversion.
*

View File

@@ -304,15 +304,9 @@ class Expr extends StmtParent, @expr {
e instanceof NoExceptExpr
or
e instanceof AlignofOperator
or
e instanceof DatasizeofOperator
)
or
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
or
exists(ConstexprIfStmt constIf |
constIf.getControllingExpr() = this.getParentWithConversions*()
)
}
/**
@@ -632,106 +626,6 @@ class ParenthesisExpr extends Conversion, @parexpr {
override string getAPrimaryQlClass() { result = "ParenthesisExpr" }
}
/**
* A node representing a C11 `_Generic` selection expression.
*
* For example:
* ```
* _Generic(e, int: "int", default: "unknown")
* ```
*/
class C11GenericExpr extends Conversion, @c11_generic {
int associationCount;
C11GenericExpr() { associationCount = (count(this.getAChild()) - 1) / 2 }
override string toString() { result = "_Generic" }
override string getAPrimaryQlClass() { result = "C11GenericExpr" }
/**
* Gets the controlling expression of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the result is `e`.
*/
Expr getControllingExpr() { result = this.getChild(0) }
/**
* Gets the type of the `n`th element in the association list of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the type of the 0th element is `int`. In the case of the default element the
* type will an instance of `VoidType`.
*/
Type getAssociationType(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 1).(TypeName).getType()
}
/**
* Gets the type of an element in the association list of the generic selection.
*/
Type getAnAssociationType() { result = this.getAssociationType(_) }
/**
* Gets the expression of the `n`th element in the association list of
* the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the expression for 0th element is `"a"`, and the expression for the
* 1st element is `"b"`. For the selected expression, this predicate
* will yield a `ReuseExpr`, such that
* ```
* this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
* ```
*/
Expr getAssociationExpr(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 2)
}
/**
* Gets the expression of an element in the association list of the generic selection.
*/
Expr getAnAssociationExpr() { result = this.getAssociationExpr(_) }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* default element.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 1.
*/
predicate isDefaultAssociation(int n) { this.getAssociationType(n) instanceof VoidType }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* one whose expression was selected.
*
* For example, with `e` of type `int` and
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 0.
*/
predicate isSelectedAssociation(int n) {
this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
}
}
/**
* A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
@@ -768,8 +662,6 @@ class AssumeExpr extends Expr, @assume {
/**
* A C/C++ comma expression.
*
* For example:
* ```
* int c = compute1(), compute2(), resulting_value;
* ```

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -290,6 +290,14 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}

View File

@@ -128,9 +128,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
or
// The children of C11 _Generic expressions are just surface syntax.
exists(C11GenericExpr generic | generic.getAChild() = expr)
or
// Do not translate implicit destructor calls for unnamed temporary variables that are
// conditionally constructed (until we have a mechanism for calling these only when the
// temporary's constructor was run)
@@ -435,9 +432,6 @@ predicate ignoreLoad(Expr expr) {
// The load is duplicated from the right operand.
isExtractorFrontendVersion65OrHigher() and expr instanceof CommaExpr
or
// The load is duplicated from the chosen expression.
expr instanceof C11GenericExpr
or
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
instanceof FunctionPointerType
or

View File

@@ -893,8 +893,7 @@ class TranslatedTransparentConversion extends TranslatedTransparentExpr {
(
expr instanceof ParenthesisExpr or
expr instanceof ReferenceDereferenceExpr or
expr instanceof ReferenceToExpr or
expr instanceof C11GenericExpr
expr instanceof ReferenceToExpr
)
}

View File

@@ -42,7 +42,6 @@ private import implementations.Accept
private import implementations.Poll
private import implementations.Select
private import implementations.MySql
private import implementations.NoexceptFunction
private import implementations.ODBC
private import implementations.SqLite3
private import implementations.PostgreSql

View File

@@ -9,14 +9,13 @@ import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
* `__builtin___memcpy_chk`.
*/
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction, NonThrowingFunction
AliasFunction
{
MemcpyFunction() {
// memcpy(dest, src, num)

View File

@@ -8,10 +8,9 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction, NonThrowingFunction
SideEffectFunction
{
MemsetFunctionModel() {
this.hasGlobalOrStdOrBslName("memset")

View File

@@ -1,11 +0,0 @@
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* A function that is annotated with a `noexcept` specifier (or the equivalent
* `throw()` specifier) guaranteeing that the function can not throw exceptions.
*
* Note: The `throw` specifier was deprecated in C++11 and removed in C++17.
*/
class NoexceptFunction extends NonThrowingFunction {
NoexceptFunction() { this.isNoExcept() or this.isNoThrow() }
}

View File

@@ -8,12 +8,11 @@
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard functions `printf`, `wprintf` and their glib variants.
*/
private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunction {
private class Printf extends FormattingFunction, AliasFunction {
Printf() {
this instanceof TopLevelFunction and
(
@@ -37,7 +36,7 @@ private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunct
/**
* The standard functions `fprintf`, `fwprintf` and their glib variants.
*/
private class Fprintf extends FormattingFunction, NonThrowingFunction {
private class Fprintf extends FormattingFunction {
Fprintf() {
this instanceof TopLevelFunction and
(
@@ -55,7 +54,7 @@ private class Fprintf extends FormattingFunction, NonThrowingFunction {
/**
* The standard function `sprintf` and its Microsoft and glib variants.
*/
private class Sprintf extends FormattingFunction, NonThrowingFunction {
private class Sprintf extends FormattingFunction {
Sprintf() {
this instanceof TopLevelFunction and
(
@@ -98,7 +97,7 @@ private class Sprintf extends FormattingFunction, NonThrowingFunction {
/**
* Implements `Snprintf`.
*/
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, NonThrowingFunction {
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
SnprintfImpl() {
this instanceof TopLevelFunction and
(
@@ -205,7 +204,7 @@ private class StringCchPrintf extends FormattingFunction {
/**
* The standard function `syslog`.
*/
private class Syslog extends FormattingFunction, NonThrowingFunction {
private class Syslog extends FormattingFunction {
Syslog() {
this instanceof TopLevelFunction and
this.hasGlobalName("syslog") and

View File

@@ -7,16 +7,13 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard function `strcat` and its wide, sized, and Microsoft variants.
*
* Does not include `strlcat`, which is covered by `StrlcatFunction`
*/
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction,
NonThrowingFunction
{
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
StrcatFunction() {
this.hasGlobalOrStdOrBslName([
"strcat", // strcat(dst, src)

View File

@@ -7,14 +7,11 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
*/
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction,
NonThrowingFunction
{
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() {
this.hasGlobalOrStdOrBslName([
"strcpy", // strcpy(dst, src)

View File

@@ -1,11 +0,0 @@
/**
* Provides an abstract class for modeling functions that never throw.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.Models
/**
* A function that is guaranteed to never throw.
*/
abstract class NonThrowingFunction extends Function { }

View File

@@ -409,11 +409,6 @@ function_defaulted(unique int id: @function ref);
function_prototyped(unique int id: @function ref)
deduction_guide_for_class(
int id: @function ref,
int class_template: @usertype ref
)
member_function_this_type(
unique int id: @function ref,
int this_type: @type ref
@@ -921,11 +916,6 @@ varspecifiers(
int spec_id: @specifier ref
);
explicit_specifier_exprs(
unique int func_id: @function ref,
int constant: @expr ref
)
attributes(
unique int id: @attribute,
int kind: int ref,
@@ -1210,7 +1200,6 @@ conversionkinds(
| @reference_to
| @ref_indirect
| @temp_init
| @c11_generic
;
/*
@@ -1789,11 +1778,6 @@ case @expr.kind of
| 382 = @isvalidwinrttype
| 383 = @iswinclass
| 384 = @iswininterface
| 385 = @istriviallyequalitycomparable
| 386 = @isscopedenum
| 387 = @istriviallyrelocatable
| 388 = @datasizeof
| 389 = @c11_generic
;
@var_args_expr = @vastartexpr
@@ -1907,9 +1891,6 @@ case @expr.kind of
| @isvalidwinrttype
| @iswinclass
| @iswininterface
| @istriviallyequalitycomparable
| @isscopedenum
| @istriviallyrelocatable
;
new_allocated_type(
@@ -1970,7 +1951,7 @@ uuidof_bind(
int type_id: @type ref
);
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof;
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof;
sizeof_bind(
unique int expr: @runtime_sizeof_or_alignof ref,

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
description: Expose C11 _Generics
compatibility: backwards

View File

@@ -1,2 +0,0 @@
description: Add new builtin operations
compatibility: backwards

View File

@@ -1,2 +0,0 @@
description: Add relation between deduction guides and class templates
compatibility: partial

View File

@@ -1,2 +0,0 @@
description: Support explicit(bool) specifiers
compatibility: partial

View File

@@ -1,22 +1,3 @@
## 1.2.1
### Minor Analysis Improvements
* The `cpp/uncontrolled-allocation-size` ("Uncontrolled allocation size") query now considers arithmetic operations that might reduce the size of user input as a barrier. The query therefore produces fewer false positive results.
## 1.2.0
### Query Metadata Changes
* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
### Minor Analysis Improvements
* Fixed false positives in the `cpp/memory-may-not-be-freed` ("Memory may not be freed") query involving class methods that returned an allocated field of that class being misidentified as allocators.
* The `cpp/incorrectly-checked-scanf` ("Incorrect return-value check for a 'scanf'-like function") query now produces fewer false positive results.
* The `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query no longer produces occasional false positive results inside template instantiations.
* The `cpp/suspicious-allocation-size` ("Not enough memory allocated for array of pointer type") query no longer produces false positives on "variable size" `struct`s.
## 1.1.0
### Query Metadata Changes

View File

@@ -39,7 +39,7 @@ predicate allocCallOrIndirect(Expr e) {
allocCallOrIndirect(rtn.getExpr())
or
// return variable assigned with alloc
exists(StackVariable v |
exists(Variable v |
v = rtn.getExpr().(VariableAccess).getTarget() and
allocCallOrIndirect(v.getAnAssignedValue()) and
not assignedToFieldOrGlobal(v, _)

View File

@@ -1,6 +1,6 @@
/**
* This file provides the `bounded` predicate that is used in `cpp/uncontrolled-arithmetic`,
* `cpp/tainted-arithmetic` and `cpp/uncontrolled-allocation-size`.
* This file provides the `bounded` predicate that is used in both `cpp/uncontrolled-arithmetic`
* and `cpp/tainted-arithmetic`.
*/
private import cpp
@@ -8,24 +8,22 @@ private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
/**
* An operand `operand` of a bitwise and expression `andExpr` (i.e., `andExpr` is either a
* `BitwiseAndExpr` or an `AssignAndExpr`) is upper bounded by some number that is less than the
* maximum integer allowed by the result type of `andExpr`.
* An operand `e` of a bitwise and expression `andExpr` (i.e., `andExpr` is either an `BitwiseAndExpr`
* or an `AssignAndExpr`) with operands `operand1` and `operand2` is the operand that is not `e` is upper
* bounded by some number that is less than the maximum integer allowed by the result type of `andExpr`.
*/
pragma[inline]
private predicate boundedBitwiseAnd(Expr operand, Expr andExpr) {
upperBound(operand.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
private predicate boundedBitwiseAnd(Expr e, Expr andExpr, Expr operand1, Expr operand2) {
operand1 != operand2 and
e = operand1 and
upperBound(operand2.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
}
/**
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operation that
* may greatly reduce the range of possible values.
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operand of an
* operation that may greatly reduce the range of possible values.
*/
predicate bounded(Expr e) {
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
// 1. `e` really cannot overflow.
// 2. `e` isn't analyzable.
// If we didn't rule out case 2 we would declare anything that isn't analyzable as bounded.
(
e instanceof UnaryArithmeticOperation or
e instanceof BinaryArithmeticOperation or
@@ -33,25 +31,25 @@ predicate bounded(Expr e) {
) and
not convertedExprMightOverflow(e)
or
// Optimistically assume that the following operations always yields a much smaller value.
e instanceof RemExpr
// Optimistically assume that a remainder expression always yields a much smaller value.
e = any(RemExpr rem).getLeftOperand()
or
e instanceof DivExpr
or
e instanceof RShiftExpr
e = any(AssignRemExpr rem).getLValue()
or
exists(BitwiseAndExpr andExpr |
e = andExpr and boundedBitwiseAnd(andExpr.getAnOperand(), andExpr)
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
)
or
// For the assignment variant of the operations we place the barrier on the assigned lvalue.
e = any(AssignRemExpr rem).getLValue()
exists(AssignAndExpr andExpr |
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
)
or
// Optimistically assume that a division always yields a much smaller value.
e = any(DivExpr div).getLeftOperand()
or
e = any(AssignDivExpr div).getLValue()
or
e = any(AssignRShiftExpr div).getLValue()
e = any(RShiftExpr shift).getLeftOperand()
or
exists(AssignAndExpr andExpr |
e = andExpr.getLValue() and boundedBitwiseAnd(andExpr.getRValue(), andExpr)
)
e = any(AssignRShiftExpr div).getLValue()
}

View File

@@ -1,9 +1,11 @@
int factor = atoi(getenv("BRANCHING_FACTOR"));
// BAD: This can allocate too little memory if factor is very large due to overflow.
char **root_node = (char **) malloc(factor * sizeof(char *));
// GOOD: Prevent overflow and unbounded allocation size by checking the input.
if (factor > 0 && factor <= 1000) {
char **root_node = (char **) malloc(factor * sizeof(char *));
// GOOD: Prevent overflow by checking the input
if (factor < 0 || factor > 1000) {
log("Factor out of range (%d)\n", factor);
return -1;
}
// This line can allocate too little memory if factor
// is very large.
char **root_node = (char **) malloc(factor * sizeof(char *));

View File

@@ -3,16 +3,12 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>This code allocates memory using a size value based on user input,
with no apparent bound on its magnitude being established. This allows
for arbitrary amounts of memory to be allocated.</p>
<p>If the allocation size is calculated by multiplying user input by a
<code>sizeof</code> expression, the multiplication can overflow. When
an integer multiplication overflows in C, the result wraps around and
can be much smaller than intended. A later attempt to write data into
the allocated memory can then be out of bounds.</p>
<p>This code calculates an allocation size by multiplying a user input
by a <code>sizeof</code> expression. Since the user input has no
apparent guard on its magnitude, this multiplication can
overflow. When an integer multiply overflows in C, the result can wrap
around and be much smaller than intended. A later attempt to put data
into the allocated buffer can then overflow.</p>
</overview>
<recommendation>

View File

@@ -1,7 +1,7 @@
/**
* @name Uncontrolled allocation size
* @description Allocating memory with a size controlled by an external user can result in
* arbitrary amounts of memory being allocated.
* @name Overflow in uncontrolled allocation size
* @description Allocating memory with a size controlled by an external
* user can result in integer overflow.
* @kind path-problem
* @problem.severity error
* @security-severity 8.1
@@ -20,7 +20,6 @@ import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import TaintedAllocationSize::PathGraph
import Bounded
/**
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
@@ -62,7 +61,16 @@ module TaintedAllocationSizeConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) {
exists(Expr e | e = node.asExpr() |
bounded(e)
// There can be two separate reasons for `convertedExprMightOverflow` not holding:
// 1. `e` really cannot overflow.
// 2. `e` isn't analyzable.
// If we didn't rule out case 2 we would place barriers on anything that isn't analyzable.
(
e instanceof UnaryArithmeticOperation or
e instanceof BinaryArithmeticOperation or
e instanceof AssignArithmeticOperation
) and
not convertedExprMightOverflow(e)
or
// Subtracting two pointers is either well-defined (and the result will likely be small), or
// terribly undefined and dangerous. Here, we assume that the programmer has ensured that the
@@ -96,6 +104,5 @@ where
isFlowSource(source.getNode(), taintCause) and
TaintedAllocationSize::flowPath(source, sink) and
allocSink(alloc, sink.getNode())
select alloc, source, sink,
"This allocation size is derived from $@ and could allocate arbitrary amounts of memory.",
select alloc, source, sink, "This allocation size is derived from $@ and might overflow.",
source.getNode(), "user input (" + taintCause + ")"

View File

@@ -16,7 +16,6 @@
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.models.implementations.NoexceptFunction
/** Gets the `Constructor` invoked when `newExpr` allocates memory. */
Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) {
@@ -45,8 +44,9 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
*/
predicate functionMayThrow(Function f) {
not f instanceof NonThrowingFunction and
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock()))
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock())) and
not f.isNoExcept() and
not f.isNoThrow()
}
/** Holds if the evaluation of `stmt` may throw an exception. */
@@ -172,7 +172,8 @@ class ThrowingAllocator extends Function {
not exists(Parameter p | p = this.getAParameter() |
p.getUnspecifiedType().stripType() instanceof NoThrowType
) and
not this instanceof NoexceptFunction
not this.isNoExcept() and
not this.isNoThrow()
)
}
}

View File

@@ -0,0 +1,4 @@
---
category: queryMetadata
---
* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query no longer produces occasional false positive results inside template instantiations.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/suspicious-allocation-size` ("Not enough memory allocated for array of pointer type") query no longer produces false positives on "variable size" `struct`s.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/incorrectly-checked-scanf` ("Incorrect return-value check for a 'scanf'-like function") query now produces fewer false positive results.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.

View File

@@ -1,12 +0,0 @@
## 1.2.0
### Query Metadata Changes
* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
### Minor Analysis Improvements
* Fixed false positives in the `cpp/memory-may-not-be-freed` ("Memory may not be freed") query involving class methods that returned an allocated field of that class being misidentified as allocators.
* The `cpp/incorrectly-checked-scanf` ("Incorrect return-value check for a 'scanf'-like function") query now produces fewer false positive results.
* The `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query no longer produces occasional false positive results inside template instantiations.
* The `cpp/suspicious-allocation-size` ("Not enough memory allocated for array of pointer type") query no longer produces false positives on "variable size" `struct`s.

View File

@@ -1,5 +0,0 @@
## 1.2.1
### Minor Analysis Improvements
* The `cpp/uncontrolled-allocation-size` ("Uncontrolled allocation size") query now considers arithmetic operations that might reduce the size of user input as a barrier. The query therefore produces fewer false positive results.

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.2.2-dev
version: 1.1.1-dev
groups:
- cpp
- queries

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --clang --edg --clang_version --edg 190000
// semmle-extractor-options: --clang --clang_version 180000
struct S {
void f() {}
@@ -108,16 +108,3 @@ bool b_is_unbounded_array2 = __is_unbounded_array(int[42]);
bool b_is_referenceable1 = __is_referenceable(int);
bool b_is_referenceable2 = __is_referenceable(void);
bool b_is_trivially_equality_comparable1 = __is_trivially_equality_comparable(int);
bool b_is_trivially_equality_comparable2 = __is_trivially_equality_comparable(void);
enum class E {
a, b
};
bool b_is_scoped_enum1 = __is_scoped_enum(E);
bool b_is_scoped_enum2 = __is_scoped_enum(int);
bool b_is_trivially_relocatable1 = __is_trivially_relocatable(int);
bool b_is_trivially_relocatable2 = __is_trivially_relocatable(void);

View File

@@ -153,21 +153,7 @@
| clang.cpp:109:28:109:50 | int | | <none> |
| clang.cpp:110:28:110:51 | __is_referenceable | void | 0 |
| clang.cpp:110:28:110:51 | void | | <none> |
| clang.cpp:112:44:112:82 | __is_trivially_equality_comparable | int | 1 |
| clang.cpp:112:44:112:82 | int | | <none> |
| clang.cpp:113:44:113:83 | __is_trivially_equality_comparable | void | 0 |
| clang.cpp:113:44:113:83 | void | | <none> |
| clang.cpp:119:26:119:44 | E | | <none> |
| clang.cpp:119:26:119:44 | __is_scoped_enum | E | 1 |
| clang.cpp:120:26:120:46 | __is_scoped_enum | int | 0 |
| clang.cpp:120:26:120:46 | int | | <none> |
| clang.cpp:122:36:122:66 | __is_trivially_relocatable | int | 1 |
| clang.cpp:122:36:122:66 | int | | <none> |
| clang.cpp:123:36:123:67 | __is_trivially_relocatable | void | 0 |
| clang.cpp:123:36:123:67 | void | | <none> |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 1 | | 1 |
| file://:0:0:0:0 | 1 | | 1 |
| file://:0:0:0:0 | 2 | | 2 |
| gcc.cpp:3:25:3:25 | 8 | | 8 |

View File

@@ -1,458 +0,0 @@
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const __va_list_tag &
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] __va_list_tag &&
generic.c:
# 3| [FormattingFunction,TopLevelFunction] int printf(char const*)
# 3| <params>:
# 3| getParameter(0): [Parameter] format
# 3| Type = [PointerType] const char *
# 14| [TopLevelFunction] int main()
# 14| <params>:
# 15| getEntryPoint(): [BlockStmt] { ... }
# 16| getStmt(0): [DeclStmt] declaration
# 16| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 16| Type = [IntType] int
# 17| getStmt(1): [DeclStmt] declaration
# 17| getDeclarationEntry(0): [VariableDeclarationEntry] definition of m
# 17| Type = [CTypedefType] MYINT
# 18| getStmt(2): [DeclStmt] declaration
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 18| Type = [PointerType] const char *
# 19| getStmt(3): [DeclStmt] declaration
# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of f
# 19| Type = [PointerType] float ***
# 21| getStmt(4): [ExprStmt] ExprStmt
# 21| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue
# 21| getArgument(0): i is %s\n
# 21| Type = [ArrayType] char[9]
# 21| Value = [StringLiteral] "i is %s\n"
# 21| ValueCategory = lvalue
# 21| getArgument(1): int
# 21| Type = [ArrayType] char[4]
# 21| Value = [StringLiteral] "int"
# 21| ValueCategory = lvalue
# 21| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 21| Conversion = [PointerConversion] pointer conversion
# 21| Type = [PointerType] const char *
# 21| ValueCategory = prvalue
# 21| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 21| Type = [CharPointerType] char *
# 21| ValueCategory = prvalue
# 21| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 21| Type = [CharPointerType] char *
# 21| ValueCategory = prvalue
# 21| getExpr(): [C11GenericExpr] _Generic
# 21| Type = [ArrayType] char[4]
# 21| Value = [C11GenericExpr] int
# 21| ValueCategory = lvalue
# 21| getControllingExpr(): [VariableAccess] i
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue(load)
# 21| getAssociationType(0): [TypeName] int
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(0): [ReuseExpr] reuse of int
# 21| Type = [ArrayType] char[4]
# 21| ValueCategory = lvalue
# 21| getAssociationType(1): [TypeName] const char *
# 21| Type = [PointerType] const char *
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(1): string
# 21| Type = [ArrayType] char[7]
# 21| Value = [StringLiteral] "string"
# 21| ValueCategory = lvalue
# 21| getAssociationType(2): [TypeName] void
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getAssociationExpr(2): unknown
# 21| Type = [ArrayType] char[8]
# 21| Value = [StringLiteral] "unknown"
# 21| ValueCategory = lvalue
# 21| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 21| Type = [IntType] int
# 21| ValueCategory = prvalue(load)
# 22| getStmt(5): [ExprStmt] ExprStmt
# 22| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getArgument(0): c is %s\n
# 22| Type = [ArrayType] char[9]
# 22| Value = [StringLiteral] "c is %s\n"
# 22| ValueCategory = lvalue
# 22| getArgument(1): int
# 22| Type = [ArrayType] char[4]
# 22| Value = [StringLiteral] "int"
# 22| ValueCategory = lvalue
# 22| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 22| Conversion = [PointerConversion] pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [CharPointerType] char *
# 22| ValueCategory = prvalue
# 22| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [CharPointerType] char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [C11GenericExpr] _Generic
# 22| Type = [ArrayType] char[4]
# 22| Value = [C11GenericExpr] int
# 22| ValueCategory = lvalue
# 22| getControllingExpr(): [VariableAccess] m
# 22| Type = [CTypedefType] MYINT
# 22| ValueCategory = prvalue(load)
# 22| getAssociationType(0): [TypeName] int
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(0): [ReuseExpr] reuse of int
# 22| Type = [ArrayType] char[4]
# 22| ValueCategory = lvalue
# 22| getAssociationType(1): [TypeName] const char *
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(1): string
# 22| Type = [ArrayType] char[7]
# 22| Value = [StringLiteral] "string"
# 22| ValueCategory = lvalue
# 22| getAssociationType(2): [TypeName] void
# 22| Type = [VoidType] void
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(2): unknown
# 22| Type = [ArrayType] char[8]
# 22| Value = [StringLiteral] "unknown"
# 22| ValueCategory = lvalue
# 22| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 22| Type = [CTypedefType] MYINT
# 22| ValueCategory = prvalue(load)
# 23| getStmt(6): [ExprStmt] ExprStmt
# 23| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getArgument(0): s is %s\n
# 23| Type = [ArrayType] char[9]
# 23| Value = [StringLiteral] "s is %s\n"
# 23| ValueCategory = lvalue
# 23| getArgument(1): string
# 23| Type = [ArrayType] char[7]
# 23| Value = [StringLiteral] "string"
# 23| ValueCategory = lvalue
# 23| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 23| Conversion = [PointerConversion] pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [CharPointerType] char *
# 23| ValueCategory = prvalue
# 23| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [CharPointerType] char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [C11GenericExpr] _Generic
# 23| Type = [ArrayType] char[7]
# 23| Value = [C11GenericExpr] string
# 23| ValueCategory = lvalue
# 23| getControllingExpr(): [VariableAccess] s
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue(load)
# 23| getAssociationType(0): [TypeName] int
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(0): int
# 23| Type = [ArrayType] char[4]
# 23| Value = [StringLiteral] "int"
# 23| ValueCategory = lvalue
# 23| getAssociationType(1): [TypeName] const char *
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(1): [ReuseExpr] reuse of string
# 23| Type = [ArrayType] char[7]
# 23| ValueCategory = lvalue
# 23| getAssociationType(2): [TypeName] void
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(2): unknown
# 23| Type = [ArrayType] char[8]
# 23| Value = [StringLiteral] "unknown"
# 23| ValueCategory = lvalue
# 23| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue(load)
# 24| getStmt(7): [ExprStmt] ExprStmt
# 24| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getArgument(0): f is %s\n
# 24| Type = [ArrayType] char[9]
# 24| Value = [StringLiteral] "f is %s\n"
# 24| ValueCategory = lvalue
# 24| getArgument(1): unknown
# 24| Type = [ArrayType] char[8]
# 24| Value = [StringLiteral] "unknown"
# 24| ValueCategory = lvalue
# 24| getArgument(0).getFullyConverted(): [CStyleCast] (const char *)...
# 24| Conversion = [PointerConversion] pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [CharPointerType] char *
# 24| ValueCategory = prvalue
# 24| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [CharPointerType] char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [C11GenericExpr] _Generic
# 24| Type = [ArrayType] char[8]
# 24| Value = [C11GenericExpr] unknown
# 24| ValueCategory = lvalue
# 24| getControllingExpr(): [VariableAccess] f
# 24| Type = [PointerType] float ***
# 24| ValueCategory = prvalue(load)
# 24| getAssociationType(0): [TypeName] int
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(0): int
# 24| Type = [ArrayType] char[4]
# 24| Value = [StringLiteral] "int"
# 24| ValueCategory = lvalue
# 24| getAssociationType(1): [TypeName] const char *
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(1): string
# 24| Type = [ArrayType] char[7]
# 24| Value = [StringLiteral] "string"
# 24| ValueCategory = lvalue
# 24| getAssociationType(2): [TypeName] void
# 24| Type = [VoidType] void
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(2): [ReuseExpr] reuse of unknown
# 24| Type = [ArrayType] char[8]
# 24| ValueCategory = lvalue
# 24| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 24| Type = [PointerType] float ***
# 24| ValueCategory = prvalue(load)
# 25| getStmt(8): [ReturnStmt] return ...
#-----| getExpr(): [Literal] 0
#-----| Type = [IntType] int
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue
generic.cpp:
# 4| [FormattingFunction,TopLevelFunction] int printf(char const*)
# 4| <params>:
# 4| getParameter(0): [Parameter] format
# 4| Type = [PointerType] const char *
# 15| [TopLevelFunction] int main()
# 15| <params>:
# 16| getEntryPoint(): [BlockStmt] { ... }
# 17| getStmt(0): [DeclStmt] declaration
# 17| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 17| Type = [IntType] int
# 18| getStmt(1): [DeclStmt] declaration
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of m
# 18| Type = [CTypedefType] MYINT
# 19| getStmt(2): [DeclStmt] declaration
# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 19| Type = [PointerType] const char *
# 20| getStmt(3): [DeclStmt] declaration
# 20| getDeclarationEntry(0): [VariableDeclarationEntry] definition of f
# 20| Type = [PointerType] float ***
# 22| getStmt(4): [ExprStmt] ExprStmt
# 22| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getArgument(0): i is %s\n
# 22| Type = [ArrayType] const char[9]
# 22| Value = [StringLiteral] "i is %s\n"
# 22| ValueCategory = lvalue
# 22| getArgument(1): int
# 22| Type = [ArrayType] const char[4]
# 22| Value = [StringLiteral] "int"
# 22| ValueCategory = lvalue
# 22| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getExpr(): [C11GenericExpr] _Generic
# 22| Type = [ArrayType] const char[4]
# 22| Value = [C11GenericExpr] int
# 22| ValueCategory = lvalue
# 22| getControllingExpr(): [VariableAccess] i
# 22| Type = [IntType] int
# 22| ValueCategory = lvalue
# 22| getAssociationType(0): [TypeName] int
# 22| Type = [IntType] int
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(0): [ReuseExpr] reuse of int
# 22| Type = [ArrayType] const char[4]
# 22| ValueCategory = lvalue
# 22| getAssociationType(1): [TypeName] const char *
# 22| Type = [PointerType] const char *
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(1): string
# 22| Type = [ArrayType] const char[7]
# 22| Value = [StringLiteral] "string"
# 22| ValueCategory = lvalue
# 22| getAssociationType(2): [TypeName] void
# 22| Type = [VoidType] void
# 22| ValueCategory = prvalue
# 22| getAssociationExpr(2): unknown
# 22| Type = [ArrayType] const char[8]
# 22| Value = [StringLiteral] "unknown"
# 22| ValueCategory = lvalue
# 22| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 22| Type = [IntType] int
# 22| ValueCategory = lvalue
# 23| getStmt(5): [ExprStmt] ExprStmt
# 23| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getArgument(0): c is %s\n
# 23| Type = [ArrayType] const char[9]
# 23| Value = [StringLiteral] "c is %s\n"
# 23| ValueCategory = lvalue
# 23| getArgument(1): int
# 23| Type = [ArrayType] const char[4]
# 23| Value = [StringLiteral] "int"
# 23| ValueCategory = lvalue
# 23| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getExpr(): [C11GenericExpr] _Generic
# 23| Type = [ArrayType] const char[4]
# 23| Value = [C11GenericExpr] int
# 23| ValueCategory = lvalue
# 23| getControllingExpr(): [VariableAccess] m
# 23| Type = [CTypedefType] MYINT
# 23| ValueCategory = lvalue
# 23| getAssociationType(0): [TypeName] int
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(0): [ReuseExpr] reuse of int
# 23| Type = [ArrayType] const char[4]
# 23| ValueCategory = lvalue
# 23| getAssociationType(1): [TypeName] const char *
# 23| Type = [PointerType] const char *
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(1): string
# 23| Type = [ArrayType] const char[7]
# 23| Value = [StringLiteral] "string"
# 23| ValueCategory = lvalue
# 23| getAssociationType(2): [TypeName] void
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getAssociationExpr(2): unknown
# 23| Type = [ArrayType] const char[8]
# 23| Value = [StringLiteral] "unknown"
# 23| ValueCategory = lvalue
# 23| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 23| Type = [CTypedefType] MYINT
# 23| ValueCategory = lvalue
# 24| getStmt(6): [ExprStmt] ExprStmt
# 24| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getArgument(0): s is %s\n
# 24| Type = [ArrayType] const char[9]
# 24| Value = [StringLiteral] "s is %s\n"
# 24| ValueCategory = lvalue
# 24| getArgument(1): string
# 24| Type = [ArrayType] const char[7]
# 24| Value = [StringLiteral] "string"
# 24| ValueCategory = lvalue
# 24| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getExpr(): [C11GenericExpr] _Generic
# 24| Type = [ArrayType] const char[7]
# 24| Value = [C11GenericExpr] string
# 24| ValueCategory = lvalue
# 24| getControllingExpr(): [VariableAccess] s
# 24| Type = [PointerType] const char *
# 24| ValueCategory = lvalue
# 24| getAssociationType(0): [TypeName] int
# 24| Type = [IntType] int
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(0): int
# 24| Type = [ArrayType] const char[4]
# 24| Value = [StringLiteral] "int"
# 24| ValueCategory = lvalue
# 24| getAssociationType(1): [TypeName] const char *
# 24| Type = [PointerType] const char *
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(1): [ReuseExpr] reuse of string
# 24| Type = [ArrayType] const char[7]
# 24| ValueCategory = lvalue
# 24| getAssociationType(2): [TypeName] void
# 24| Type = [VoidType] void
# 24| ValueCategory = prvalue
# 24| getAssociationExpr(2): unknown
# 24| Type = [ArrayType] const char[8]
# 24| Value = [StringLiteral] "unknown"
# 24| ValueCategory = lvalue
# 24| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 24| Type = [PointerType] const char *
# 24| ValueCategory = lvalue
# 25| getStmt(7): [ExprStmt] ExprStmt
# 25| getExpr(): [FormattingFunctionCall,FunctionCall] call to printf
# 25| Type = [IntType] int
# 25| ValueCategory = prvalue
# 25| getArgument(0): f is %s\n
# 25| Type = [ArrayType] const char[9]
# 25| Value = [StringLiteral] "f is %s\n"
# 25| ValueCategory = lvalue
# 25| getArgument(1): unknown
# 25| Type = [ArrayType] const char[8]
# 25| Value = [StringLiteral] "unknown"
# 25| ValueCategory = lvalue
# 25| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getExpr(): [C11GenericExpr] _Generic
# 25| Type = [ArrayType] const char[8]
# 25| Value = [C11GenericExpr] unknown
# 25| ValueCategory = lvalue
# 25| getControllingExpr(): [VariableAccess] f
# 25| Type = [PointerType] float ***
# 25| ValueCategory = lvalue
# 25| getAssociationType(0): [TypeName] int
# 25| Type = [IntType] int
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(0): int
# 25| Type = [ArrayType] const char[4]
# 25| Value = [StringLiteral] "int"
# 25| ValueCategory = lvalue
# 25| getAssociationType(1): [TypeName] const char *
# 25| Type = [PointerType] const char *
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(1): string
# 25| Type = [ArrayType] const char[7]
# 25| Value = [StringLiteral] "string"
# 25| ValueCategory = lvalue
# 25| getAssociationType(2): [TypeName] void
# 25| Type = [VoidType] void
# 25| ValueCategory = prvalue
# 25| getAssociationExpr(2): [ReuseExpr] reuse of unknown
# 25| Type = [ArrayType] const char[8]
# 25| ValueCategory = lvalue
# 25| getControllingExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 25| Type = [PointerType] float ***
# 25| ValueCategory = lvalue
# 26| getStmt(8): [ReturnStmt] return ...
#-----| getExpr(): [Literal] 0
#-----| Type = [IntType] int
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue

View File

@@ -1 +0,0 @@
semmle/code/cpp/PrintAST.ql

View File

@@ -1,8 +0,0 @@
| generic.c:21:22:21:32 | _Generic | generic.c:21:22:21:32 | describe(val) |
| generic.c:22:22:22:32 | _Generic | generic.c:22:22:22:32 | describe(val) |
| generic.c:23:22:23:32 | _Generic | generic.c:23:22:23:32 | describe(val) |
| generic.c:24:22:24:32 | _Generic | generic.c:24:22:24:32 | describe(val) |
| generic.cpp:22:22:22:32 | _Generic | generic.cpp:22:22:22:32 | describe(val) |
| generic.cpp:23:22:23:32 | _Generic | generic.cpp:23:22:23:32 | describe(val) |
| generic.cpp:24:22:24:32 | _Generic | generic.cpp:24:22:24:32 | describe(val) |
| generic.cpp:25:22:25:32 | _Generic | generic.cpp:25:22:25:32 | describe(val) |

View File

@@ -1,5 +0,0 @@
import cpp
from C11GenericExpr g, MacroInvocation m
where m.getAnExpandedElement() = g
select g, m

View File

@@ -11,14 +11,14 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:10 |
| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | provenance | MaD:644 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:7:10:7:18 | call to ymlSource | provenance | Src:MaD:642 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:643 |
| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | provenance | MaD:2 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:7:10:7:18 | call to ymlSource | provenance | Src:MaD:0 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:1 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:13:18:13:18 | x | provenance | |
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:13:10:13:16 | call to ymlStep | provenance | |
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:643 |
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:1 |
| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | provenance | |
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | provenance | MaD:644 |
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | provenance | MaD:2 |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |

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