Merge branch 'github:main' into am0o0-python-codeExec

This commit is contained in:
Am
2024-05-09 23:15:56 +02:00
committed by GitHub
220 changed files with 10931 additions and 8994 deletions

View File

@@ -14,6 +14,10 @@ build:linux --cxxopt=-std=c++20
build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
# this requires developer mode, but is required to have pack installer functioning
startup --windows_enable_symlinks
common --enable_runfiles
common --registry=file:///%workspace%/misc/bazel/registry
common --registry=https://bcr.bazel.build

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 //:buildifier"; exit 1
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
)

View File

@@ -26,7 +26,14 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //:buildifier
entry: bazel run //misc/bazel:buildifier
pass_filenames: false
- id: go-gen
name: Check checked in generated files in go
files: ^go/.*
language: system
entry: bazel run //go:gen
pass_filenames: false
- id: codeql-format

View File

@@ -1,9 +0,0 @@
load("@buildifier_prebuilt//:rules.bzl", "buildifier")
buildifier(
name = "buildifier",
exclude_patterns = [
"./.git/*",
],
lint_mode = "fix",
)

View File

@@ -4,6 +4,8 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/codeql-queries) on [codeql.github.com](https://codeql.github.com).
Note that the CodeQL for Visual Studio Code documentation has been migrated to https://docs.github.com/en/code-security/codeql-for-vs-code/, but you can still contribute to it via a different repository. For more information, see [Contributing to GitHub Docs documentation](https://docs.github.com/en/contributing)."
## Change notes
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
@@ -43,7 +45,7 @@ If you have an idea for a query that you would like to share with other CodeQL u
3. **Formatting**
- The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code).
- The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/).
If you prefer, you can either:
1. install the [pre-commit framework](https://pre-commit.com/) and install the configured hooks on this repo via `pre-commit install`, or

View File

@@ -13,7 +13,8 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "platforms", version = "0.0.9")
bazel_dep(name = "rules_go", version = "0.47.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
@@ -21,6 +22,7 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
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 = "gazelle", version = "0.36.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
@@ -52,6 +54,9 @@ node.toolchain(
)
use_repo(node, "nodejs", "nodejs_toolchains")
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.22.2")
register_toolchains(
"@nodejs_toolchains//:all",
)

View File

@@ -4,7 +4,7 @@ This open source repository contains the standard CodeQL libraries and queries t
## How do I learn CodeQL and run queries?
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL using the [CodeQL extension for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) and the [CodeQL CLI](https://codeql.github.com/docs/codeql-cli/).
There is extensive documentation about the [CodeQL language](https://codeql.github.com/docs/), writing CodeQL using the [CodeQL extension for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/) and using the [CodeQL CLI](https://docs.github.com/en/code-security/codeql-cli).
## Contributing

View File

@@ -9,6 +9,7 @@ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedInitialization
private import DataFlowPrivate
import SsaInternalsCommon
@@ -104,8 +105,8 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
cached
private newtype TDefImpl =
TDefAddressImpl(BaseIRVariable v) or
TDirectDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
isDef(_, _, address, base, _, indirectionIndex)
TDirectDefImpl(Operand address, int indirectionIndex) {
isDef(_, _, address, _, _, indirectionIndex)
} or
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
// Represents the initial "definition" of a global variable when entering
@@ -115,8 +116,8 @@ private newtype TDefImpl =
cached
private newtype TUseImpl =
TDirectUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
isUse(_, operand, base, _, indirectionIndex) and
TDirectUseImpl(Operand operand, int indirectionIndex) {
isUse(_, operand, _, _, indirectionIndex) and
not isDef(true, _, operand, _, _, _)
} or
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
@@ -210,19 +211,11 @@ abstract class DefImpl extends TDefImpl {
*/
abstract int getIndirection();
/**
* Gets the instruction that computes the base of this definition or use.
* This is always a `VariableAddressInstruction` or an `CallInstruction`.
*/
abstract BaseSourceVariableInstruction getBase();
/**
* Gets the base source variable (i.e., the variable without
* any indirection) of this definition or use.
*/
final BaseSourceVariable getBaseSourceVariable() {
this.getBase().getBaseSourceVariable() = result
}
abstract BaseSourceVariable getBaseSourceVariable();
/** Gets the variable that is defined or used. */
SourceVariable getSourceVariable() {
@@ -282,19 +275,11 @@ abstract class UseImpl extends TUseImpl {
/** Gets the indirection index of this use. */
final int getIndirectionIndex() { result = indirectionIndex }
/**
* Gets the instruction that computes the base of this definition or use.
* This is always a `VariableAddressInstruction` or an `CallInstruction`.
*/
abstract BaseSourceVariableInstruction getBase();
/**
* Gets the base source variable (i.e., the variable without
* any indirection) of this definition or use.
*/
final BaseSourceVariable getBaseSourceVariable() {
this.getBase().getBaseSourceVariable() = result
}
abstract BaseSourceVariable getBaseSourceVariable();
/** Gets the variable that is defined or used. */
SourceVariable getSourceVariable() {
@@ -329,6 +314,17 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
v.getIndirection() = ind
}
/**
* Gets the instruction that computes the address that's used to
* initialize `v`.
*/
private Instruction getInitializationTargetAddress(IRVariable v) {
exists(TranslatedVariableInitialization init |
init.getIRVariable() = v and
result = init.getTargetAddress()
)
}
/** An initial definition of an `IRVariable`'s address. */
private class DefAddressImpl extends DefImpl, TDefAddressImpl {
BaseIRVariable v;
@@ -347,8 +343,15 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
final override Node0Impl getValue() { none() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
block = v.getIRVariable().getEnclosingIRFunction().getEntryBlock() and
index = 0
exists(IRVariable var | var = v.getIRVariable() |
block.getInstruction(index) = getInitializationTargetAddress(var)
or
// If there is no translatated element that does initialization of the
// variable we place the SSA definition at the entry block of the function.
not exists(getInitializationTargetAddress(var)) and
block = var.getEnclosingIRFunction().getEntryBlock() and
index = 0
)
}
override Cpp::Location getLocation() { result = v.getIRVariable().getLocation() }
@@ -358,14 +361,13 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
result.getIndirection() = 0
}
final override BaseSourceVariableInstruction getBase() { none() }
final override BaseSourceVariable getBaseSourceVariable() { result = v }
}
private class DirectDef extends DefImpl, TDirectDefImpl {
Operand address;
BaseSourceVariableInstruction base;
DirectDef() { this = TDirectDefImpl(base, address, indirectionIndex) }
DirectDef() { this = TDirectDefImpl(address, indirectionIndex) }
override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() }
@@ -377,30 +379,36 @@ private class DirectDef extends DefImpl, TDirectDefImpl {
override Operand getAddressOperand() { result = address }
override BaseSourceVariableInstruction getBase() { result = base }
private BaseSourceVariableInstruction getBase() {
isDef(_, _, address, result, _, indirectionIndex)
}
override int getIndirection() { isDef(_, _, address, base, result, indirectionIndex) }
override BaseSourceVariable getBaseSourceVariable() {
result = this.getBase().getBaseSourceVariable()
}
override Node0Impl getValue() { isDef(_, result, address, base, _, _) }
override int getIndirection() { isDef(_, _, address, _, result, indirectionIndex) }
override predicate isCertain() { isDef(true, _, address, base, _, indirectionIndex) }
override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
override predicate isCertain() { isDef(true, _, address, _, _, indirectionIndex) }
}
private class DirectUseImpl extends UseImpl, TDirectUseImpl {
Operand operand;
BaseSourceVariableInstruction base;
DirectUseImpl() { this = TDirectUseImpl(base, operand, indirectionIndex) }
DirectUseImpl() { this = TDirectUseImpl(operand, indirectionIndex) }
override string toString() { result = "Use of " + this.getSourceVariable() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation.
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
if this.getBase().getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op, int indirection |
exists(Operand op, int indirection, Instruction base |
indirection = this.getIndirection() and
base = this.getBase() and
op =
min(Operand cand, int i |
isUse(_, cand, base, indirection, indirectionIndex) and
@@ -413,15 +421,19 @@ private class DirectUseImpl extends UseImpl, TDirectUseImpl {
else operand.getUse() = block.getInstruction(index)
}
final override BaseSourceVariableInstruction getBase() { result = base }
private BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, indirectionIndex) }
override BaseSourceVariable getBaseSourceVariable() {
result = this.getBase().getBaseSourceVariable()
}
final Operand getOperand() { result = operand }
final override Cpp::Location getLocation() { result = operand.getLocation() }
override int getIndirection() { isUse(_, operand, base, result, indirectionIndex) }
override int getIndirection() { isUse(_, operand, _, result, indirectionIndex) }
override predicate isCertain() { isUse(true, operand, base, _, indirectionIndex) }
override predicate isCertain() { isUse(true, operand, _, _, indirectionIndex) }
override Node getNode() { nodeHasOperand(result, operand, indirectionIndex) }
}
@@ -480,13 +492,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
result instanceof UnknownDefaultLocation
}
override BaseSourceVariableInstruction getBase() {
exists(InitializeParameterInstruction init |
init.getParameter() = p and
// This is always a `VariableAddressInstruction`
result = init.getAnOperand().getDef()
)
}
override BaseIRVariable getBaseSourceVariable() { result.getIRVariable().getAst() = p }
}
/**
@@ -572,8 +578,8 @@ class GlobalUse extends UseImpl, TGlobalUse {
)
}
override SourceVariable getSourceVariable() {
sourceVariableIsGlobal(result, global, f, this.getIndirection())
override BaseSourceVariable getBaseSourceVariable() {
baseSourceVariableIsGlobal(result, global, f)
}
final override Cpp::Location getLocation() { result = f.getLocation() }
@@ -590,8 +596,6 @@ class GlobalUse extends UseImpl, TGlobalUse {
Type getUnderlyingType() { result = global.getUnderlyingType() }
override predicate isCertain() { any() }
override BaseSourceVariableInstruction getBase() { none() }
}
/**
@@ -621,8 +625,8 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
}
/** Gets the global variable associated with this definition. */
override SourceVariable getSourceVariable() {
sourceVariableIsGlobal(result, global, f, this.getIndirection())
override BaseSourceVariable getBaseSourceVariable() {
baseSourceVariableIsGlobal(result, global, f)
}
override int getIndirection() { result = indirectionIndex }
@@ -645,8 +649,6 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
override string toString() { result = "Def of " + this.getSourceVariable() }
override Location getLocation() { result = f.getLocation() }
override BaseSourceVariableInstruction getBase() { none() }
}
/**
@@ -959,11 +961,10 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
)
}
private predicate sourceVariableIsGlobal(
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
private predicate baseSourceVariableIsGlobal(
BaseIRVariable base, GlobalLikeVariable global, IRFunction func
) {
exists(IRVariable irVar, BaseIRVariable base |
sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and
exists(IRVariable irVar |
irVar = base.getIRVariable() and
irVar.getEnclosingIRFunction() = func and
global = irVar.getAst() and

View File

@@ -830,6 +830,12 @@ newtype TTranslatedElement =
not ignoreExpr(dc)
)
} or
// The set of destructors to invoke after a handler for a `try` statement. These
// need to be special cased because the destructors need to run following an
// `ExceptionEdge`, but not following a `GotoEdge` edge.
TTranslatedDestructorsAfterHandler(Handler handler) {
exists(handler.getAnImplicitDestructorCall())
} or
// A precise side effect of an argument to a `Call`
TTranslatedArgumentExprSideEffect(Call call, Expr expr, int n, SideEffectOpcode opcode) {
not ignoreExpr(expr) and

View File

@@ -777,6 +777,72 @@ abstract class TranslatedHandler extends TranslatedStmt {
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
}
/**
* The IR translation of the destructor calls of the parent `TranslatedCatchByTypeHandler`.
*
* This object does not itself generate the destructor calls. Instead, its
* children provide the actual calls.
*/
class TranslatedDestructorsAfterHandler extends TranslatedElement,
TTranslatedDestructorsAfterHandler
{
Handler handler;
TranslatedDestructorsAfterHandler() { this = TTranslatedDestructorsAfterHandler(handler) }
override string toString() { result = "Destructor calls after handler: " + handler }
private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
result.getExpr() = handler.getImplicitDestructorCall(id)
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
}
override Handler getAst() { result = handler }
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override TranslatedElement getChild(int id) {
result = this.getTranslatedImplicitDestructorCall(id)
}
override predicate handlesDestructorsExplicitly() { any() }
override Declaration getFunction() { result = handler.getEnclosingFunction() }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
exists(int id | child = this.getChild(id) |
// Transition to the next child, if any.
result = this.getChild(id + 1).getFirstInstruction(kind)
or
// And otherwise go to the next handler, if any.
not exists(this.getChild(id + 1)) and
result =
getTranslatedStmt(handler)
.getParent()
.(TranslatedTryStmt)
.getNextHandler(getTranslatedStmt(handler), kind)
)
}
override TranslatedElement getLastChild() {
result =
this.getTranslatedImplicitDestructorCall(max(int id |
exists(handler.getImplicitDestructorCall(id))
))
}
override Instruction getALastInstructionInternal() {
result = this.getLastChild().getALastInstruction()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
}
/**
* The IR translation of a C++ `catch` block that catches an exception with a
* specific type (e.g. `catch (const std::exception&)`).
@@ -790,10 +856,14 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
resultType = getVoidType()
}
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
result = super.getChildInternal(id)
or
id = 0 and result = this.getParameter()
or
id = 1 and result = this.getDestructors()
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -810,7 +880,9 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
result = this.getParameter().getFirstInstruction(kind)
or
kind instanceof ExceptionEdge and
result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
if exists(this.getDestructors())
then result = this.getDestructors().getFirstInstruction(any(GotoEdge edge))
else result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
)
}
@@ -822,6 +894,8 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
private TranslatedParameter getParameter() {
result = getTranslatedParameter(stmt.getParameter())
}
private TranslatedDestructorsAfterHandler getDestructors() { result.getAst() = stmt }
}
/**
@@ -842,9 +916,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
}
}
class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override IfStmt stmt;
abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
@@ -857,6 +929,8 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
override predicate handlesDestructorsExplicitly() { any() }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -867,25 +941,21 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
id = 3 and result = this.getElse()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
abstract predicate hasInitialization();
private TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
abstract TranslatedStmt getInitialization();
private TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
abstract TranslatedCondition getCondition();
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
abstract TranslatedStmt getThen();
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
abstract TranslatedStmt getElse();
private predicate hasElse() { exists(stmt.getElse()) }
abstract predicate hasElse();
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
@@ -898,7 +968,11 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
else (
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
)
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -906,7 +980,24 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
result = this.getParent().getChildSuccessor(this, kind)
(
if this.hasAnImplicitDestructorCall()
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
)
or
exists(int destructorId |
destructorId >= this.getFirstDestructorCallIndex() and
child = this.getChild(destructorId) and
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
)
or
exists(int lastDestructorIndex |
lastDestructorIndex =
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
child = this.getChild(lastDestructorIndex) and
result = this.getParent().getChildSuccessor(this, kind)
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -914,76 +1005,44 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
}
}
class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
override ConstexprIfStmt stmt;
class TranslatedIfStmt extends TranslatedIfLikeStmt {
override IfStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
}
override predicate hasInitialization() { exists(stmt.getInitialization()) }
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
id = 1 and result = this.getCondition()
or
id = 2 and result = this.getThen()
or
id = 3 and result = this.getElse()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
private TranslatedStmt getInitialization() {
override TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
private TranslatedCondition getCondition() {
override TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
override predicate hasElse() { exists(stmt.getElse()) }
}
class TranslatedConstExprIfStmt extends TranslatedIfLikeStmt {
override ConstexprIfStmt stmt;
override predicate hasInitialization() { exists(stmt.getInitialization()) }
override TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
private predicate hasElse() { exists(stmt.getElse()) }
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction(kind)
override TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
}
override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
result = this.getParent().getChildSuccessor(this, kind)
}
override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
override Instruction getALastInstructionInternal() {
result = this.getThen().getALastInstruction()
or
result = this.getElse().getALastInstruction()
}
override predicate hasElse() { exists(stmt.getElse()) }
}
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {

View File

@@ -14,13 +14,32 @@ the program, or security vulnerabilities, by allowing an attacker to overwrite a
</overview>
<recommendation>
<p>
Ensure that all execution paths deallocate the allocated memory at most once. If possible, reassign
the pointer to a null value after deallocating it. This will prevent double-free vulnerabilities since
most deallocation functions will perform a null-pointer check before attempting to deallocate the memory.
Ensure that all execution paths deallocate the allocated memory at most once. In complex cases it may
help to reassign a pointer to a null value after deallocating it. This will prevent double-free vulnerabilities
since most deallocation functions will perform a null-pointer check before attempting to deallocate memory.
</p>
</recommendation>
<example><sample src="DoubleFree.cpp" />
<example>
<p>
In the following example, <code>buff</code> is allocated and then freed twice:
</p>
<sample src="DoubleFreeBad.cpp" />
<p>
Reviewing the code above, the issue can be fixed by simply deleting the additional call to
<code>free(buff)</code>.
</p>
<sample src="DoubleFreeGood.cpp" />
<p>
In the next example, <code>task</code> may be deleted twice, if an exception occurs inside the <code>try</code>
block after the first <code>delete</code>:
</p>
<sample src="DoubleFreeBad2.cpp" />
<p>
The problem can be solved by assigning a null value to the pointer after the first <code>delete</code>, as
calling <code>delete</code> a second time on the null pointer is harmless.
</p>
<sample src="DoubleFreeGood2.cpp" />
</example>
<references>

View File

@@ -0,0 +1,16 @@
void g() {
MyTask *task = nullptr;
try
{
task = new MyTask;
...
delete task;
...
} catch (...) {
delete task; // BAD: potential double-free
}
}

View File

@@ -0,0 +1,7 @@
int* f() {
int *buff = malloc(SIZE*sizeof(int));
do_stuff(buff);
free(buff); // GOOD: buff is only freed once.
int *new_buffer = malloc(SIZE*sizeof(int));
return new_buffer;
}

View File

@@ -0,0 +1,17 @@
void g() {
MyTask *task = nullptr;
try
{
task = new MyTask;
...
delete task;
task = nullptr;
...
} catch (...) {
delete task; // GOOD: harmless if task is NULL
}
}

View File

@@ -22,10 +22,8 @@ function.
</example>
<references>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
<li>Microsoft C Runtime Library Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, wprintf</a>.</li>
</references>
</qhelp>

View File

@@ -30,11 +30,8 @@ function.
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude user input from format strings</a>.</li>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
<li>Microsoft C Runtime Library Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, wprintf</a>.</li>
</references>
</qhelp>

View File

@@ -1,4 +0,0 @@
int main() {
printf("%s\n", 42); //printf will treat 42 as a char*, will most likely segfault
return 0;
}

View File

@@ -15,18 +15,22 @@ the function.
</p>
</recommendation>
<example><sample src="WrongTypeFormatArguments.cpp" />
<example>
<p>In the following example, the wrong format specifier is given for an integer format argument:</p>
<sample src="WrongTypeFormatArgumentsBad.cpp" />
<p>The corrected version uses <code>%i</code> as the format specifier for the integer format argument:</p>
<sample src="WrongTypeFormatArgumentsGood.cpp" />
</example>
<references>
<li>CERT C Coding
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude user input from format strings</a>.</li>
<li>cplusplus.com: <a href="http://www.tutorialspoint.com/cplusplus/cpp_functions.htm">C++ Functions</a>.</li>
<li>CRT Alphabetical Function Reference: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l">printf, _printf_l, wprintf, _wprintf_l</a>.</li>
<li>Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-170">Format specification syntax: printf and wprintf functions</a>.</li>
<li>cplusplus.com:<a href="https://cplusplus.com/reference/cstdio/printf/"></a>printf</li>
<li>CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO47-C.+Use+valid+format+strings">FIO47-C. Use valid format strings</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,4 @@
int main() {
printf("%s\n", 42); // BAD: printf will treat 42 as a char*, will most likely segfault
return 0;
}

View File

@@ -0,0 +1,4 @@
int main() {
printf("%i\n", 42); // GOOD: printf will treat 42 as an int
return 0;
}

View File

@@ -2,7 +2,7 @@
void f_warning(int i)
{
// The usage of the logical not operator in this case is unlikely to be correct
// BAD: the usage of the logical not operator in this case is unlikely to be correct
// as the output is being used as an operator for a bit-wise and operation
if (i & !FLAGS)
{
@@ -10,10 +10,9 @@ void f_warning(int i)
}
}
void f_fixed(int i)
{
if (i & ~FLAGS) // Changing the logical not operator for the bit-wise not operator would fix this logic
if (i & ~FLAGS) // GOOD: Changing the logical not operator for the bit-wise not operator would fix this logic
{
// code
}

View File

@@ -16,7 +16,13 @@
<p>Carefully inspect the flagged expressions. Consider the intent in the code logic, and decide whether it is necessary to change the not operator.</p>
</recommendation>
<example><sample src="IncorrectNotOperatorUsage.cpp" /></example>
<example>
<p>Here is an example of this issue and how it can be fixed:</p>
<sample src="IncorrectNotOperatorUsage.cpp" />
<p>In other cases, particularly when the expressions have <code>bool</code> type, the fix may instead be of the form <code>a &amp;&amp; !b</code>.</p>
</example>
<references>
<li>

View File

@@ -1,2 +0,0 @@
strncpy(dest, src, sizeof(src)); //wrong: size of dest should be used
strncpy(dest, src, strlen(src)); //wrong: size of dest should be used

View File

@@ -12,14 +12,20 @@ or equal to the size of the destination buffer. Calls of the form <code>strncpy(
not the source buffer.</p>
</recommendation>
<example><sample src="StrncpyFlippedArgs.cpp" />
<example>
<p>In the following examples, the size of the source buffer is incorrectly used as a parameter to <code>strncpy</code>:</p>
<sample src="StrncpyFlippedArgsBad.cpp" />
<p>The corrected version uses the size of the destination buffer, or a variable containing the size of the destination buffer as the size parameter to <code>strncpy</code>:</p>
<sample src="StrncpyFlippedArgsGood.cpp" />
</example>
<references>
<li>cplusplus.com: <a href="http://www.cplusplus.com/reference/clibrary/cstring/strncpy/">strncpy</a>.</li>
<li>cplusplus.com: <a href="https://cplusplus.com/reference/cstring/strncpy/">strncpy</a>.</li>
<li>
I. Gerg. <em>An Overview and Example of the Buffer-Overflow Exploit</em>. IANewsletter vol 7 no 4. 2005.
</li>

View File

@@ -0,0 +1,9 @@
char src[256];
char dest1[128];
...
strncpy(dest1, src, sizeof(src)); // wrong: size of dest should be used
char *dest2 = (char *)malloc(sz1 + sz2 + sz3);
strncpy(dest2, src, strlen(src)); // wrong: size of dest should be used

View File

@@ -0,0 +1,10 @@
char src[256];
char dest1[128];
...
strncpy(dest1, src, sizeof(dest1)); // correct
size_t destSize = sz1 + sz2 + sz3;
char *dest2 = (char *)malloc(destSize);
strncpy(dest2, src, destSize); // correct

View File

@@ -1,22 +0,0 @@
int main(int argc, char** argv) {
char *userAndFile = argv[2];
{
char fileBuffer[FILENAME_MAX] = "/home/";
char *fileName = fileBuffer;
size_t len = strlen(fileName);
strncat(fileName+len, userAndFile, FILENAME_MAX-len-1);
// BAD: a string from the user is used in a filename
fopen(fileName, "wb+");
}
{
char fileBuffer[FILENAME_MAX] = "/home/";
char *fileName = fileBuffer;
size_t len = strlen(fileName);
// GOOD: use a fixed file
char* fixed = "jim/file.txt";
strncat(fileName+len, fixed, FILENAME_MAX-len-1);
fopen(fileName, "wb+");
}
}

View File

@@ -7,32 +7,53 @@
can result in sensitive information being revealed or deleted, or an attacker being able to influence
behavior by modifying unexpected files.</p>
<p>Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
such as "..". Such a path may potentially point to any directory on the filesystem.</p>
<p>Paths that are naively constructed from data controlled by a user may be absolute paths, or may contain
unexpected special characters such as "..". Such a path could point anywhere on the file system.</p>
</overview>
<recommendation>
<p>Validate user input before using it to construct a filepath. Ideally, follow these rules:</p>
<p>Validate user input before using it to construct a file path.</p>
<ul>
<li>Do not allow more than a single "." character.</li>
<li>Do not allow directory separators such as "/" or "\" (depending on the filesystem).</li>
<li>Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
".../...//" the resulting string would still be "../".</li>
<li>Ideally use a whitelist of known good patterns.</li>
</ul>
<p>Common validation methods include checking that the normalized path is relative and does not contain
any ".." components, or checking that the path is contained within a safe folder. The method you should use depends
on how the path is used in the application, and whether the path should be a single path component.
</p>
<p>If the path should be a single path component (such as a file name), you can check for the existence
of any path separators ("/" or "\"), or ".." sequences in the input, and reject the input if any are found.
</p>
<p>
Note that removing "../" sequences is <i>not</i> sufficient, since the input could still contain a path separator
followed by "..". For example, the input ".../...//" would still result in the string "../" if only "../" sequences
are removed.
</p>
<p>Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
the user input matches one of these patterns.</p>
</recommendation>
<example>
<p>In this example, a username and file are read from the arguments to main and then used to access a file in the
user's home directory. However, a malicious user could enter a filename which contains special
characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
"/home/[user]/../../etc/passwd", which is the system's password file. This could potentially allow them to
access all the system's passwords.</p>
<p>In this example, a file name is read from a user and then used to access a file.
However, a malicious user could enter a file name anywhere on the file system,
such as "/etc/passwd" or "../../../etc/passwd".</p>
<sample src="TaintedPath.c" />
<sample src="examples/TaintedPath.c" />
<p>
If the input should only be a file name, you can check that it doesn't contain any path separators or ".." sequences.
</p>
<sample src="examples/TaintedPathNormalize.c" />
<p>
If the input should be within a specific directory, you can check that the resolved path
is still contained within that directory.
</p>
<sample src="examples/TaintedPathFolder.c" />
</example>
<references>
@@ -41,6 +62,7 @@ access all the system's passwords.</p>
OWASP:
<a href="https://owasp.org/www-community/attacks/Path_Traversal">Path Traversal</a>.
</li>
<li>Linux man pages: <a href="https://man7.org/linux/man-pages/man3/realpath.3.html">realpath(3)</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,10 @@
int main(int argc, char** argv) {
char *userAndFile = argv[2];
{
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
// BAD: a string from the user is used in a filename
fopen(fileBuffer, "wb+");
}
}

View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char *userAndFile = argv[2];
const char *baseDir = "/home/user/public/";
char fullPath[PATH_MAX];
// Attempt to concatenate the base directory and the user-supplied path
snprintf(fullPath, sizeof(fullPath), "%s%s", baseDir, userAndFile);
// Resolve the absolute path, normalizing any ".." or "."
char *resolvedPath = realpath(fullPath, NULL);
if (resolvedPath == NULL) {
perror("Error resolving path");
return 1;
}
// Check if the resolved path starts with the base directory
if (strncmp(baseDir, resolvedPath, strlen(baseDir)) != 0) {
free(resolvedPath);
return 1;
}
// GOOD: Path is within the intended directory
FILE *file = fopen(resolvedPath, "wb+");
free(resolvedPath);
}

View File

@@ -0,0 +1,16 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char *fileName = argv[2];
// Check for invalid sequences in the user input
if (strstr(fileName , "..") || strchr(fileName , '/') || strchr(fileName , '\\')) {
printf("Invalid filename.\n");
return 1;
}
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
// GOOD: We know that the filename is safe and stays within the public folder
FILE *file = fopen(fileBuffer, "wb+");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -2191,6 +2191,7 @@ public:
void set_x(char y) { *x = y; }
char get_x() { return *x; }
operator bool() const;
};
constexpr bool initialization_with_destructor_bool = true;
@@ -2530,4 +2531,25 @@ void destruction_in_switch_3(int c) {
}
}
void destructor_possibly_not_handled() {
ClassWithDestructor x;
try {
throw 42;
}
catch(char) {
}
}
ClassWithDestructor getClassWithDestructor();
void this_inconsistency(bool b) {
if (const ClassWithDestructor& a = getClassWithDestructor())
;
}
void constexpr_inconsistency(bool b) {
if constexpr (const ClassWithDestructor& a = getClassWithDestructor(); initialization_with_destructor_bool)
;
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -36,6 +36,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -27,6 +27,7 @@ invalidOverlap
nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
| ir.cpp:2546:34:2546:34 | Call: call to operator bool | Call instruction 'Call: call to operator bool' has a `this` argument operand that is not an address, in function '$@'. | ir.cpp:2545:6:2545:23 | void this_inconsistency(bool) | void this_inconsistency(bool) |
nonUniqueIRVariable
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |
| coroutines.cpp:87:20:87:20 | VariableAddress: (unnamed local variable) | Variable address instruction 'VariableAddress: (unnamed local variable)' has no associated variable, in function '$@'. | coroutines.cpp:87:20:87:33 | co_returnable_void co_return_void() | co_returnable_void co_return_void() |

View File

@@ -71,3 +71,22 @@ void macroUsage(unsigned int arg1, unsigned int arg2)
}
}
void bool_examples(bool a, bool b)
{
if (a & !b) // dubious (confusing intent, but shouldn't produce a wrong result)
{
}
if (a & ~b)
{
}
if (a && ~b)
{
}
if (a && !b)
{
}
}

View File

@@ -14,3 +14,4 @@
| IncorrectNotOperatorUsage.cpp:48:9:48:18 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:49:9:49:20 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:70:10:70:34 | ... \| ... | Usage of a logical not (!) expression as a bitwise operator. |
| IncorrectNotOperatorUsage.cpp:77:9:77:14 | ... & ... | Usage of a logical not (!) expression as a bitwise operator. |

View File

@@ -2,6 +2,8 @@ edges
| test.c:8:27:8:30 | **argv | test.c:9:23:9:29 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:31:22:31:28 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:69:14:69:20 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:80:25:80:31 | *access to array | provenance | |
| test.c:8:27:8:30 | **argv | test.c:88:22:88:28 | *access to array | provenance | |
| test.c:9:23:9:29 | *access to array | test.c:17:11:17:18 | *fileName | provenance | TaintFunction |
| test.c:31:22:31:28 | *access to array | test.c:32:11:32:18 | *fileName | provenance | |
| test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | *fileName | provenance | |
@@ -11,6 +13,8 @@ edges
| test.c:54:21:54:26 | *call to getenv | test.c:55:11:55:16 | *buffer | provenance | TaintFunction |
| test.c:74:13:74:18 | read output argument | test.c:76:11:76:16 | *buffer | provenance | |
| test.c:75:13:75:18 | read output argument | test.c:76:11:76:16 | *buffer | provenance | |
| test.c:80:25:80:31 | *access to array | test.c:84:11:84:20 | *fileBuffer | provenance | TaintFunction |
| test.c:88:22:88:28 | *access to array | test.c:98:24:98:33 | *fileBuffer | provenance | TaintFunction |
nodes
| test.c:8:27:8:30 | **argv | semmle.label | **argv |
| test.c:9:23:9:29 | *access to array | semmle.label | *access to array |
@@ -30,6 +34,10 @@ nodes
| test.c:74:13:74:18 | read output argument | semmle.label | read output argument |
| test.c:75:13:75:18 | read output argument | semmle.label | read output argument |
| test.c:76:11:76:16 | *buffer | semmle.label | *buffer |
| test.c:80:25:80:31 | *access to array | semmle.label | *access to array |
| test.c:84:11:84:20 | *fileBuffer | semmle.label | *fileBuffer |
| test.c:88:22:88:28 | *access to array | semmle.label | *access to array |
| test.c:98:24:98:33 | *fileBuffer | semmle.label | *fileBuffer |
subpaths
#select
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | **argv | test.c:17:11:17:18 | *fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
@@ -41,3 +49,5 @@ subpaths
| test.c:69:14:69:20 | access to array | test.c:8:27:8:30 | **argv | test.c:69:14:69:20 | *access to array | This argument to a file access function is derived from $@ and then passed to readFile(fileName), which calls fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
| test.c:76:11:76:16 | buffer | test.c:74:13:74:18 | read output argument | test.c:76:11:76:16 | *buffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:74:13:74:18 | read output argument | user input (buffer read by read) |
| test.c:76:11:76:16 | buffer | test.c:75:13:75:18 | read output argument | test.c:76:11:76:16 | *buffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:75:13:75:18 | read output argument | user input (buffer read by read) |
| test.c:84:11:84:20 | fileBuffer | test.c:8:27:8:30 | **argv | test.c:84:11:84:20 | *fileBuffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |
| test.c:98:24:98:33 | fileBuffer | test.c:8:27:8:30 | **argv | test.c:98:24:98:33 | *fileBuffer | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | **argv | user input (a command-line argument) |

View File

@@ -2,7 +2,7 @@
// Associated with CWE-022: Improper Limitation of a Pathname to a Restricted Directory. http://cwe.mitre.org/data/definitions/22.html
#include "stdlib.h"
#define PATH_MAX 4096
///// Test code /////
int main(int argc, char** argv) {
@@ -75,6 +75,55 @@ int main(int argc, char** argv) {
read(0, buffer, 1024);
fopen(buffer, "wb+"); // BAD [duplicated with both sources]
}
{
char *userAndFile = argv[2];
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
// BAD: a string from the user is used in a filename
fopen(fileBuffer, "wb+");
}
{
char *fileName = argv[2];
// Check for invalid sequences in the user input
if (strstr(fileName , "..") || strchr(fileName , '/') || strchr(fileName , '\\')) {
printf("Invalid filename.\n");
return 1;
}
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
// GOOD: We know that the filename is safe and stays within the public folder. But we currently get an FP here.
FILE *file = fopen(fileBuffer, "wb+");
}
{
char *userAndFile = argv[2];
const char *baseDir = "/home/user/public/";
char fullPath[PATH_MAX];
// Attempt to concatenate the base directory and the user-supplied path
snprintf(fullPath, sizeof(fullPath), "%s%s", baseDir, userAndFile);
// Resolve the absolute path, normalizing any ".." or "."
char *resolvedPath = realpath(fullPath, 0); // <- we're using `NULL` in the example, but 0 here to get it to compile. Same for next line.
if (resolvedPath == 0) {
perror("Error resolving path");
return 1;
}
// Check if the resolved path starts with the base directory
if (strncmp(baseDir, resolvedPath, strlen(baseDir)) != 0) {
free(resolvedPath);
return 1;
}
// GOOD: Path is within the intended directory
FILE *file = fopen(resolvedPath, "wb+");
free(resolvedPath);
}
}
void readFile(char *fileName) {

View File

@@ -1,6 +1,5 @@
| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:683:31:683:32 | call to at | This object is destroyed at the end of the full-expression. |
| test.cpp:689:46:689:58 | pointer to ~vector output argument | This object is destroyed at the end of the full-expression. |
| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed at the end of the full-expression. |
| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed at the end of the full-expression. |

View File

@@ -686,7 +686,7 @@ void test() {
for (auto x : returnRef()[0]) {} // GOOD
for (auto x : returnRef().at(0)) {} // GOOD
for(auto it = returnValue().begin(); it != returnValue().end(); ++it) {} // BAD
for(auto it = returnValue().begin(); it != returnValue().end(); ++it) {} // BAD [NOT DETECTED]
{
auto v = returnValue();
@@ -793,3 +793,12 @@ void test4() {
// call can flow to `begin` through the back-edge and cause a strange FP.
auto zero = A().size();
}
void test5(int i)
{
while(i < 10) {
const auto& vvs = returnValue();
for(const auto& vs : vvs) { }
++i;
} // GOOD
}

View File

@@ -22,3 +22,4 @@
| test.cpp:416:2:418:2 | for(...;...;...) ... | test.cpp:416:18:416:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:424:2:425:2 | for(...;...;...) ... | test.cpp:424:18:424:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:433:2:434:2 | for(...;...;...) ... | test.cpp:433:18:433:22 | 0 | 0 | | { ... } | 0 | return ... |
| test.cpp:559:3:564:3 | while (...) ... | test.cpp:559:9:559:15 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |

View File

@@ -13,6 +13,7 @@ nodes
| test.cpp:458:6:458:6 | definition of x | semmle.label | definition of x |
| test.cpp:464:6:464:6 | definition of x | semmle.label | definition of x |
| test.cpp:471:6:471:6 | definition of x | semmle.label | definition of x |
| test.cpp:557:15:557:15 | definition of r | semmle.label | definition of r |
#select
| test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
| test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
@@ -27,3 +28,4 @@ nodes
| test.cpp:460:7:460:7 | x | test.cpp:458:6:458:6 | definition of x | test.cpp:458:6:458:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:458:6:458:6 | x | x |
| test.cpp:467:2:467:2 | x | test.cpp:464:6:464:6 | definition of x | test.cpp:464:6:464:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:464:6:464:6 | x | x |
| test.cpp:474:7:474:7 | x | test.cpp:471:6:471:6 | definition of x | test.cpp:471:6:471:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:471:6:471:6 | x | x |
| test.cpp:567:7:567:7 | r | test.cpp:557:15:557:15 | definition of r | test.cpp:557:15:557:15 | definition of r | The variable $@ may not be initialized at this access. | test.cpp:557:15:557:15 | r | r |

View File

@@ -1,6 +1,6 @@
// Semmle test cases for rule CWE-457.
void use(int data);
void use(...);
void test1() {
int foo = 1;
@@ -545,3 +545,24 @@ int static_method_false_positive(){
StaticMethodClass *t;
int i = t->get(); // GOOD: the `get` method is static and this is equivalent to StaticMethodClass::get()
}
struct LinkedList
{
LinkedList* next;
};
bool getBool();
void test45() {
LinkedList *r, *s, **rP = &r;
while(getBool())
{
s = new LinkedList;
*rP = s;
rP = &s->next;
}
*rP = NULL;
use(r); // GOOD [FALSE POSITIVE]
}

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.codedom.Compiler
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for user input treated as code vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for user input treated as code vulnerabilities.

View File

@@ -6,6 +6,7 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.controlflow.BasicBlocks
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.Net
@@ -14,12 +15,12 @@ private import semmle.code.csharp.security.SensitiveActions
/**
* A data flow source for user-controlled bypass of sensitive method.
*/
abstract class Source extends DataFlow::Node { }
abstract class Source extends ApiSourceNode { }
/**
* A data flow sink for user-controlled bypass of sensitive method.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/** Gets the 'MethodCall' which is considered sensitive. */
abstract MethodCall getSensitiveMethodCall();
}

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
private import semmle.code.csharp.security.PrivateData
@@ -15,7 +16,7 @@ abstract class Source extends DataFlow::ExprNode { }
/**
* A data flow sink for private information flowing unencrypted to an external location.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for private information flowing unencrypted to an external location.

View File

@@ -9,6 +9,7 @@ private import semmle.code.csharp.frameworks.Moq
private import semmle.code.csharp.frameworks.system.web.Security
private import semmle.code.csharp.frameworks.system.security.cryptography.X509Certificates
private import semmle.code.csharp.frameworks.Test
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
/**
* A data flow source for hard coded credentials.
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::ExprNode { }
/**
* A data flow sink for hard coded credentials.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/**
* Gets a description of this sink, including a placeholder for the sink and a placeholder for
* the supplementary element.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.DirectoryServices
private import semmle.code.csharp.frameworks.system.directoryservices.Protocols
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for unvalidated user input that is used to construct LDAP queries.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for unvalidated user input that is used to construct LDAP queries.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in log entries.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in log entries.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.Xml
private import semmle.code.csharp.security.Sanitizers
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
* A data flow sink for untrusted user input processed as XML without validation against a known
* schema.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/** Gets a string describing the reason why this is a sink. */
abstract string getReason();
}

View File

@@ -5,6 +5,7 @@
import csharp
private import semmle.code.csharp.dataflow.DataFlow2
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
private import semmle.code.csharp.security.Sanitizers
@@ -17,7 +18,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in dangerous regular expression operations.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in dangerous regular expression operations.

View File

@@ -4,6 +4,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used to construct regular expressions.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used to construct regular expressions.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.Data
private import semmle.code.csharp.security.Sanitizers
@@ -15,7 +16,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in resource descriptors.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in resource descriptors.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.Sql
private import semmle.code.csharp.security.Sanitizers
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A sink for SQL injection vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for SQL injection vulnerabilities.

View File

@@ -5,6 +5,7 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.IO
private import semmle.code.csharp.frameworks.system.Web
@@ -18,7 +19,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for uncontrolled data in path expression vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for uncontrolled data in path expression vulnerabilities.

View File

@@ -6,6 +6,7 @@
import csharp
private import semmle.code.csharp.serialization.Deserializers
private import semmle.code.csharp.dataflow.TaintTracking2
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
/**
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for unsafe deserialization vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends ApiSinkNode { }
/**
* A data flow sink for unsafe deserialization vulnerabilities to an instance method.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.frameworks.Format
@@ -20,7 +21,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for unvalidated URL redirect vulnerabilities.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for unvalidated URL redirect vulnerabilities.

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
@@ -19,7 +20,7 @@ private class ThreatModelSource extends Source instanceof ThreatModelFlowSource
/**
* A data flow sink for untrusted user input used in XML processing.
*/
abstract class Sink extends DataFlow::ExprNode {
abstract class Sink extends ApiSinkExprNode {
/**
* Gets the reason for the insecurity of this sink.
*/

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private import semmle.code.csharp.frameworks.system.xml.XPath
private import semmle.code.csharp.frameworks.system.Xml
@@ -16,7 +17,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for untrusted user input used in XPath expression.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for untrusted user input used in XPath expression.

View File

@@ -4,6 +4,7 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
/**
* A data flow source for unsafe zip extraction.
@@ -13,7 +14,7 @@ abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for unsafe zip extraction.
*/
abstract class Sink extends DataFlow::ExprNode { }
abstract class Sink extends ApiSinkExprNode { }
/**
* A sanitizer for unsafe zip extraction.

View File

@@ -1,84 +0,0 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */
private import semmle.code.csharp.dataflow.internal.ExternalFlow
/**
* A data flow sink node.
*/
abstract class SinkNode extends DataFlow::Node { }
/**
* Module that adds all sinks to `SinkNode`, excluding sinks for cryptography based
* queries, and queries where sinks are not succifiently explicit.
*/
private module AllSinks {
private import ParallelSink as ParallelSink
private import Remote as Remote
private import semmle.code.csharp.security.dataflow.CodeInjectionQuery as CodeInjectionQuery
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery as ExposureOfPrivateInformationQuery
private import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentialsQuery
private import semmle.code.csharp.security.dataflow.LDAPInjectionQuery as LdapInjectionQuery
private import semmle.code.csharp.security.dataflow.LogForgingQuery as LogForgingQuery
private import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery as MissingXmlValidationQuery
private import semmle.code.csharp.security.dataflow.ReDoSQuery as ReDosQuery
private import semmle.code.csharp.security.dataflow.RegexInjectionQuery as RegexInjectionQuery
private import semmle.code.csharp.security.dataflow.ResourceInjectionQuery as ResourceInjectionQuery
private import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjectionQuery
private import semmle.code.csharp.security.dataflow.TaintedPathQuery as TaintedPathQuery
private import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery as UnsafeDeserializationQuery
private import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirectQuery
private import semmle.code.csharp.security.dataflow.XMLEntityInjectionQuery as XmlEntityInjectionQuery
private import semmle.code.csharp.security.dataflow.XPathInjectionQuery as XpathInjectionQuery
private import semmle.code.csharp.security.dataflow.XSSSinks as XssSinks
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery
private class ParallelSink extends SinkNode instanceof ParallelSink::ParallelSink { }
private class RemoteSinkFlowSinks extends SinkNode instanceof Remote::RemoteFlowSink { }
private class CodeInjectionSink extends SinkNode instanceof CodeInjectionQuery::Sink { }
private class ConditionalBypassSink extends SinkNode instanceof ConditionalBypassQuery::Sink { }
private class ExposureOfPrivateInformationSink extends SinkNode instanceof ExposureOfPrivateInformationQuery::Sink
{ }
private class HardcodedCredentialsSink extends SinkNode instanceof HardcodedCredentialsQuery::Sink
{ }
private class LdapInjectionSink extends SinkNode instanceof LdapInjectionQuery::Sink { }
private class LogForgingSink extends SinkNode instanceof LogForgingQuery::Sink { }
private class MissingXmlValidationSink extends SinkNode instanceof MissingXmlValidationQuery::Sink
{ }
private class ReDosSink extends SinkNode instanceof ReDosQuery::Sink { }
private class RegexInjectionSink extends SinkNode instanceof RegexInjectionQuery::Sink { }
private class ResourceInjectionSink extends SinkNode instanceof ResourceInjectionQuery::Sink { }
private class SqlInjectionSink extends SinkNode instanceof SqlInjectionQuery::Sink { }
private class TaintedPathSink extends SinkNode instanceof TaintedPathQuery::Sink { }
private class UnsafeDeserializationSink extends SinkNode instanceof UnsafeDeserializationQuery::Sink
{ }
private class UrlRedirectSink extends SinkNode instanceof UrlRedirectQuery::Sink { }
private class XmlEntityInjectionSink extends SinkNode instanceof XmlEntityInjectionQuery::Sink { }
private class XpathInjectionSink extends SinkNode instanceof XpathInjectionQuery::Sink { }
private class XssSink extends SinkNode instanceof XssSinks::Sink { }
/**
* Add all models as data sinks.
*/
private class SinkNodeExternal extends SinkNode {
SinkNodeExternal() { sinkNode(this, _) }
}
}

View File

@@ -0,0 +1,35 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */
private import semmle.code.csharp.dataflow.internal.ExternalFlow
private import semmle.code.csharp.security.dataflow.flowsinks.FlowSinks
/**
* A data flow sink node.
*/
final class SinkNode = ApiSinkNode;
/**
* Module that adds all API like sinks to `SinkNode`, excluding sinks for cryptography based
* queries, and queries where sinks are not sufficiently defined (eg. using broad method name matching).
*/
private module AllApiSinks {
private import ParallelSink
private import Remote
private import semmle.code.csharp.security.dataflow.CodeInjectionQuery as CodeInjectionQuery
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery as ExposureOfPrivateInformationQuery
private import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentialsQuery
private import semmle.code.csharp.security.dataflow.LDAPInjectionQuery as LdapInjectionQuery
private import semmle.code.csharp.security.dataflow.LogForgingQuery as LogForgingQuery
private import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery as MissingXmlValidationQuery
private import semmle.code.csharp.security.dataflow.ReDoSQuery as ReDosQuery
private import semmle.code.csharp.security.dataflow.RegexInjectionQuery as RegexInjectionQuery
private import semmle.code.csharp.security.dataflow.ResourceInjectionQuery as ResourceInjectionQuery
private import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjectionQuery
private import semmle.code.csharp.security.dataflow.TaintedPathQuery as TaintedPathQuery
private import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery as UnsafeDeserializationQuery
private import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirectQuery
private import semmle.code.csharp.security.dataflow.XMLEntityInjectionQuery as XmlEntityInjectionQuery
private import semmle.code.csharp.security.dataflow.XPathInjectionQuery as XpathInjectionQuery
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery
}

View File

@@ -3,6 +3,7 @@
*/
import csharp
private import FlowSinks
private import Remote
private import semmle.code.csharp.commons.Loggers
private import semmle.code.csharp.frameworks.system.Web
@@ -16,7 +17,7 @@ private import semmle.code.csharp.dataflow.internal.ExternalFlow
* which the application may have no access control. For example, files on a local or remote
* filesystem (including log files and cookies).
*/
abstract class ExternalLocationSink extends DataFlow::ExprNode { }
abstract class ExternalLocationSink extends ApiSinkExprNode { }
private class ExternalModelSink extends ExternalLocationSink {
ExternalModelSink() { sinkNode(this, "file-content-store") }

View File

@@ -0,0 +1,23 @@
/** Provides classes representing various flow sinks for data flow / taint tracking. */
private import csharp
private import semmle.code.csharp.dataflow.internal.ExternalFlow
/**
* A data flow sink node for an API, which should be considered
* supported from a modeling perspective.
*/
abstract class ApiSinkNode extends DataFlow::Node { }
/**
* A data flow sink expression node for an API, which should be considered
* supported from a modeling perspective.
*/
abstract class ApiSinkExprNode extends ApiSinkNode, DataFlow::ExprNode { }
/**
* Add all sink models as data sinks.
*/
private class ApiSinkNodeExternal extends ApiSinkNode {
ApiSinkNodeExternal() { sinkNode(this, _) }
}

View File

@@ -3,11 +3,12 @@
*/
import csharp
private import FlowSinks
/**
* A data flow sink node for parallel execution.
*/
abstract class ParallelSink extends DataFlow::Node { }
abstract class ParallelSink extends ApiSinkNode { }
/**
* A data flow sink node for lambda parallel sink.

View File

@@ -5,12 +5,13 @@
import csharp
private import Email::Email
private import ExternalLocationSink
private import FlowSinks
private import Html
private import semmle.code.csharp.security.dataflow.XSSSinks as XssSinks
private import semmle.code.csharp.frameworks.system.web.UI
/** A data flow sink of remote user output. */
abstract class RemoteFlowSink extends DataFlow::Node { }
abstract class RemoteFlowSink extends ApiSinkNode { }
/**
* A value written to the `[Inner]Text` property of an object defined in the

View File

@@ -1,77 +0,0 @@
/** Provides classes representing various flow sources for data flow / taint tracking. */
private import semmle.code.csharp.dataflow.internal.ExternalFlow
/**
* A data flow source node.
*/
abstract class SourceNode extends DataFlow::Node { }
/**
* Module that adds all sources to `SourceNode`, excluding source for cryptography based
* queries, and queries where sources are not succifiently explicit or mainly hardcoded constants.
*/
private module AllSources {
private import FlowSources as FlowSources
private import semmle.code.csharp.security.cryptography.HardcodedSymmetricEncryptionKey
private import semmle.code.csharp.security.dataflow.CleartextStorageQuery as CleartextStorageQuery
private import semmle.code.csharp.security.dataflow.CodeInjectionQuery as CodeInjectionQuery
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery as ExposureOfPrivateInformationQuery
private import semmle.code.csharp.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentialsQuery
private import semmle.code.csharp.security.dataflow.LDAPInjectionQuery as LdapInjectionQuery
private import semmle.code.csharp.security.dataflow.LogForgingQuery as LogForgingQuery
private import semmle.code.csharp.security.dataflow.MissingXMLValidationQuery as MissingXmlValidationQuery
private import semmle.code.csharp.security.dataflow.ReDoSQuery as ReDosQuery
private import semmle.code.csharp.security.dataflow.RegexInjectionQuery as RegexInjectionQuery
private import semmle.code.csharp.security.dataflow.ResourceInjectionQuery as ResourceInjectionQuery
private import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjectionQuery
private import semmle.code.csharp.security.dataflow.TaintedPathQuery as TaintedPathQuery
private import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery as UnsafeDeserializationQuery
private import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirectQuery
private import semmle.code.csharp.security.dataflow.XMLEntityInjectionQuery as XmlEntityInjectionQuery
private import semmle.code.csharp.security.dataflow.XPathInjectionQuery as XpathInjectionQuery
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery
private class FlowSourcesSources extends SourceNode instanceof FlowSources::SourceNode { }
private class CodeInjectionSource extends SourceNode instanceof CodeInjectionQuery::Source { }
private class ConditionalBypassSource extends SourceNode instanceof ConditionalBypassQuery::Source
{ }
private class LdapInjectionSource extends SourceNode instanceof LdapInjectionQuery::Source { }
private class LogForgingSource extends SourceNode instanceof LogForgingQuery::Source { }
private class MissingXmlValidationSource extends SourceNode instanceof MissingXmlValidationQuery::Source
{ }
private class ReDosSource extends SourceNode instanceof ReDosQuery::Source { }
private class RegexInjectionSource extends SourceNode instanceof RegexInjectionQuery::Source { }
private class ResourceInjectionSource extends SourceNode instanceof ResourceInjectionQuery::Source
{ }
private class SqlInjectionSource extends SourceNode instanceof SqlInjectionQuery::Source { }
private class TaintedPathSource extends SourceNode instanceof TaintedPathQuery::Source { }
private class UnsafeDeserializationSource extends SourceNode instanceof UnsafeDeserializationQuery::Source
{ }
private class UrlRedirectSource extends SourceNode instanceof UrlRedirectQuery::Source { }
private class XmlEntityInjectionSource extends SourceNode instanceof XmlEntityInjectionQuery::Source
{ }
private class XpathInjectionSource extends SourceNode instanceof XpathInjectionQuery::Source { }
/**
* Add all models as data sources.
*/
private class SourceNodeExternal extends SourceNode {
SourceNodeExternal() { sourceNode(this, _) }
}
}

View File

@@ -0,0 +1,14 @@
/** Provides classes representing various flow sources for data flow / taint tracking. */
private import FlowSources as FlowSources
final class SourceNode = FlowSources::SourceNode;
/**
* Module that adds all API like sources to `SourceNode`, excluding some sources for cryptography based
* queries, and queries where sources are not sufficiently defined (eg. using broad method name matching).
*/
private module AllApiSources {
private import semmle.code.csharp.security.dataflow.ConditionalBypassQuery as ConditionalBypassQuery
private import semmle.code.csharp.security.dataflow.ZipSlipQuery as ZipSlipQuery
}

View File

@@ -32,3 +32,18 @@ class ThreatModelFlowSource extends DataFlow::Node {
)
}
}
/**
* A data flow source node for an API, which should be considered
* supported from a modeling perspective.
*/
abstract class ApiSourceNode extends DataFlow::Node { }
private class AddSourceNodes extends ApiSourceNode instanceof SourceNode { }
/**
* Add all source models as data sources.
*/
private class ApiSourceNodeExternal extends ApiSourceNode {
ApiSourceNodeExternal() { sourceNode(this, _) }
}

View File

@@ -8,8 +8,8 @@ private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlow
private import semmle.code.csharp.dataflow.internal.ExternalFlow
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
private import semmle.code.csharp.security.dataflow.flowsources.AllSources
private import semmle.code.csharp.security.dataflow.flowsinks.AllSinks
private import semmle.code.csharp.security.dataflow.flowsources.ApiSources as ApiSources
private import semmle.code.csharp.security.dataflow.flowsinks.ApiSinks as ApiSinks
private import TestLibrary
/** Holds if the given callable is not worth supporting. */
@@ -85,11 +85,11 @@ class ExternalApi extends Callable {
/** Holds if this API is a known source. */
pragma[nomagic]
predicate isSource() { this.getAnOutput() instanceof SourceNode }
predicate isSource() { this.getAnOutput() instanceof ApiSources::SourceNode }
/** Holds if this API is a known sink. */
pragma[nomagic]
predicate isSink() { this.getAnInput() instanceof SinkNode }
predicate isSink() { this.getAnInput() instanceof ApiSinks::SinkNode }
/** Holds if this API is a known neutral. */
pragma[nomagic]

View File

@@ -5,6 +5,8 @@
About CodeQL for Visual Studio Code
=================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
CodeQL for Visual Studio Code is an extension that lets you write, run, and test CodeQL queries in Visual Studio Code.
Features

View File

@@ -5,6 +5,8 @@
About telemetry in CodeQL for Visual Studio Code
=================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
If you specifically opt in to permit GitHub to do so, GitHub will collect usage data and metrics for the purposes of helping the core developers to improve the CodeQL extension for VS Code.
This data will not be shared with any parties outside of GitHub. IP addresses and installation IDs will be retained for a maximum of 30 days. Anonymous data will be retained for a maximum of 180 days.

View File

@@ -5,6 +5,8 @@
Analyzing your projects
=================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can run queries on CodeQL databases and view the results in Visual Studio Code. This article explains how to get a CodeQL database and analyze it on your local machine. For information on running analysis at scale across many CodeQL databases, see ":ref:`Running CodeQL queries at scale with multi-repository variant analysis <running-codeql-queries-at-scale-with-mrva>`."
Choosing a database

View File

@@ -5,6 +5,8 @@
Customizing settings
====================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can edit the settings for the CodeQL extension to suit your needs.
About CodeQL extension settings

View File

@@ -5,6 +5,8 @@
Exploring data flow with path queries
=====================================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can run CodeQL queries in VS Code to help you track the flow of data through a program, highlighting areas that are potential security vulnerabilities.
About path queries

View File

@@ -5,6 +5,8 @@
Exploring the structure of your source code
=================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can use the AST viewer to display the abstract syntax tree of a CodeQL database.
About the abstract syntax tree

View File

@@ -3,6 +3,8 @@
CodeQL for Visual Studio Code
=============================
.. include:: ../reusables/vs-code-deprecation-note.rst
The CodeQL extension for Visual Studio Code adds rich language support for CodeQL and allows you to easily find problems in codebases.
- :doc:`About CodeQL for Visual Studio Code

View File

@@ -5,6 +5,8 @@
Running CodeQL queries at scale with multi-repository variant analysis
======================================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
.. include:: ../reusables/beta-note-mrva.rst
About multi-repository variant analysis

View File

@@ -5,6 +5,8 @@
Setting up CodeQL in Visual Studio Code
=================================================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can install and configure the CodeQL extension in Visual Studio Code.
.. include:: ../reusables/license-note.rst

View File

@@ -5,6 +5,8 @@
Testing CodeQL queries in Visual Studio Code
============================================
.. include:: ../reusables/vs-code-deprecation-note.rst
You can run unit tests for CodeQL queries using the Visual Studio Code extension. When you are sure that your query finds the results you want to identify, you can use variant analysis to run it at scale. For information on running analysis at scale across many CodeQL databases, see ":ref:`Running CodeQL queries at scale with multi-repository variant analysis <running-codeql-queries-at-scale-with-mrva>`."
About testing queries in VS Code

View File

@@ -5,6 +5,8 @@
Troubleshooting CodeQL for Visual Studio Code
=============================================
.. include:: ../reusables/vs-code-deprecation-note.rst
This article explains how to debug problems with the analysis of CodeQL databases that are stored on your local
machine. For information on troubleshooting variant analysis, which runs on GitHub.com, see
":ref:`Troubleshooting variant analysis <troubleshooting-variant-analysis>`."

View File

@@ -5,6 +5,8 @@
Troubleshooting variant analysis
================================
.. include:: ../reusables/vs-code-deprecation-note.rst
.. include:: ../reusables/beta-note-mrva.rst
This article explains how to debug problems with variant analysis, that is, analysis run using GitHub Actions

View File

@@ -5,6 +5,8 @@
Using the CodeQL model editor
=============================
.. include:: ../reusables/vs-code-deprecation-note.rst
.. include:: ../reusables/beta-note-model-pack-editor-vsc.rst
You can view, write, and edit CodeQL packs in Visual Studio Code using the CodeQL extension. The model editor is designed to help you model external dependencies of your codebase that are not supported by the standard CodeQL Libraries.

View File

@@ -5,6 +5,8 @@
Working with CodeQL packs in Visual Studio Code
===============================================
.. include:: ../reusables/vs-code-deprecation-note.rst
.. include:: ../reusables/beta-note-package-management.rst
You can view, write, and edit all types of CodeQL packs in Visual Studio Code using the CodeQL extension.

View File

@@ -73,7 +73,7 @@ The CodeQL examples in this article are only excerpts and are not meant to repre
Abstract syntax
---------------
The abstract syntax tree (AST) represents the elements of the source code organized into a tree. The `AST viewer <https://codeql.github.com/docs/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code/>`__
The abstract syntax tree (AST) represents the elements of the source code organized into a tree. The `AST viewer <https://docs.github.com/en/code-security/codeql-for-vs-code/using-the-advanced-functionality-of-the-codeql-for-vs-code-extension/exploring-the-structure-of-your-source-code/>`__
in Visual Studio Code shows the AST nodes, including the relevant CodeQL classes and predicates.
All CodeQL AST classes inherit from the `AstNode` class, which provides the following member predicates

View File

@@ -70,8 +70,8 @@ Query execution
After you've created a CodeQL database, one or more queries are executed
against it. CodeQL queries are written in a specially-designed object-oriented
query language called QL. You can run the queries checked out from the CodeQL
repo (or custom queries that you've written yourself) using the :ref:`CodeQL
for VS Code extension <codeql-for-visual-studio-code>` or the `CodeQL CLI
repo (or custom queries that you've written yourself) using the `CodeQL
for VS Code extension <https://docs.github.com/en/code-security/codeql-for-vs-code/>`__ or the `CodeQL CLI
<https://docs.github.com/en/code-security/codeql-cli>`__. For more information about queries, see ":ref:`About CodeQL queries <about-codeql-queries>`."
.. _interpret-query-results:

View File

@@ -82,7 +82,7 @@ Bug Fixes
Python
""""""
* The `View AST functionality <https://codeql.github.com/docs/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code/>`__ no longer prints detailed information about regular expressions, greatly improving performance.
* The `View AST functionality <https://docs.github.com/en/code-security/codeql-for-vs-code/using-the-advanced-functionality-of-the-codeql-for-vs-code-extension/exploring-the-structure-of-your-source-code/>`__ no longer prints detailed information about regular expressions, greatly improving performance.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -53,5 +53,5 @@ CodeQL for Visual Studio Code
You can analyze CodeQL databases in Visual Studio Code using the CodeQL
extension, which provides an enhanced environment for writing and running custom
queries and viewing the results. For more information, see ":ref:`CodeQL
for Visual Studio Code <codeql-for-visual-studio-code>`."
queries and viewing the results. For more information, see "`CodeQL
for Visual Studio Code <https://docs.github.com/en/code-security/codeql-for-vs-code/>`__."

View File

@@ -9,7 +9,7 @@ CodeQL for C/C++
Setup
=====
For this example you need to set up `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__ and download the CodeQL database for `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__ from GitHub.
For this example you need to set up `CodeQL for Visual Studio Code <https://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/installing-codeql-for-vs-code>`__ and download the CodeQL database for `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__ from GitHub.
Checking for overflow in C
==========================

View File

@@ -11,7 +11,7 @@ CodeQL for C/C++
Setup
=====
For this example you need to set up `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__ and download the CodeQL database for `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__ from GitHub.
For this example you need to set up `CodeQL for Visual Studio Code <https://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/installing-codeql-for-vs-code/>`__ and download the CodeQL database for `ChakraCore <https://github.com/Chakra-Core/ChakraCore/>`__ from GitHub.
.. rst-class:: agenda

View File

@@ -9,7 +9,7 @@ Finding string formatting vulnerabilities in C/C++
Setup
=====
For this example you need to set up `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__ and download the CodeQL database for `dotnet/coreclr <https://github.com/dotnet/coreclr>`__ from GitHub.
For this example you need to set up `CodeQL for Visual Studio Code <hhttps://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/installing-codeql-for-vs-code>`__ and download the CodeQL database for `dotnet/coreclr <https://github.com/dotnet/coreclr>`__ from GitHub.
.. rst-class:: agenda

View File

@@ -9,7 +9,7 @@ CodeQL for C/C++
Setup
=====
For this example you need to set up `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__ and download the CodeQL database for `dotnet/coreclr <https://github.com/dotnet/coreclr>`__ from GitHub.
For this example you need to set up `CodeQL for Visual Studio Code <https://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/installing-codeql-for-vs-code>`__ and download the CodeQL database for `dotnet/coreclr <https://github.com/dotnet/coreclr>`__ from GitHub.
.. rst-class:: agenda

View File

@@ -9,7 +9,7 @@ CodeQL for C/C++
Setup
=====
For this example you need to set up `CodeQL for Visual Studio Code <https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/>`__ and download the CodeQL database for `exiv2 <https://github.com/Exiv2/exiv2>`__ from GitHub.
For this example you need to set up `CodeQL for Visual Studio Code <https://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/installing-codeql-for-vs-code>`__ and download the CodeQL database for `exiv2 <https://github.com/Exiv2/exiv2>`__ from GitHub.
.. Include language-agnostic section here

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