mirror of
https://github.com/github/codeql.git
synced 2026-04-24 08:15:14 +02:00
Merge branch 'main' into redsun82/swift-6
This commit is contained in:
2
.github/codeql/codeql-config.yml
vendored
2
.github/codeql/codeql-config.yml
vendored
@@ -9,3 +9,5 @@ paths-ignore:
|
||||
- '/python/'
|
||||
- '/javascript/ql/test'
|
||||
- '/javascript/extractor/tests'
|
||||
- '/rust/ql/test'
|
||||
- '/rust/ql/integration-tests'
|
||||
|
||||
7
.github/workflows/rust-analysis.yml
vendored
7
.github/workflows/rust-analysis.yml
vendored
@@ -55,12 +55,7 @@ jobs:
|
||||
with:
|
||||
tools: ${{ steps.codeql.outputs.nightly_bundle }}
|
||||
languages: ${{ matrix.language }}
|
||||
config: |
|
||||
disable-default-queries: true
|
||||
queries:
|
||||
- uses: security-and-quality
|
||||
paths-ignore:
|
||||
- '/rust/ql/tests'
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@main
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
## 2.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.
|
||||
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
|
||||
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.
|
||||
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
|
||||
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.
|
||||
12
cpp/ql/lib/change-notes/released/2.1.0.md
Normal file
12
cpp/ql/lib/change-notes/released/2.1.0.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## 2.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.
|
||||
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
|
||||
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.
|
||||
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.0.2
|
||||
lastReleaseVersion: 2.1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 2.0.3-dev
|
||||
version: 2.1.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -281,3 +281,9 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
|
||||
}
|
||||
|
||||
private predicate iteratorDereference(Call c) { c.getTarget() instanceof IteratorReferenceFunction }
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -212,3 +212,30 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut, string
|
||||
nodeOut = callOutput(call, modelOut)
|
||||
)
|
||||
}
|
||||
|
||||
import SpeculativeTaintFlow
|
||||
|
||||
private module SpeculativeTaintFlow {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
exists(DataFlowCall call, ArgumentPosition argpos |
|
||||
// TODO: exclude neutrals and anything that has QL modeling.
|
||||
not exists(DataFlowDispatch::viableCallable(call)) and
|
||||
src.(DataFlowPrivate::ArgumentNode).argumentOf(call, argpos)
|
||||
|
|
||||
not argpos.(DirectPosition).getIndex() = -1 and
|
||||
sink.(PostUpdateNode)
|
||||
.getPreUpdateNode()
|
||||
.(DataFlowPrivate::ArgumentNode)
|
||||
.argumentOf(call, any(DirectPosition qualpos | qualpos.getIndex() = -1))
|
||||
or
|
||||
sink.(DataFlowPrivate::OutNode).getCall() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +196,8 @@ private predicate isInvalidFunction(Function func) {
|
||||
expr.getEnclosingFunction() = func and
|
||||
not exists(expr.getType())
|
||||
)
|
||||
or
|
||||
count(func.getEntryPoint().getLocation()) > 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 1.2.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Remove results from the `cpp/wrong-type-format-argument` ("Wrong type of arguments to formatting function") query if the argument is the return value of an implicitly declared function.
|
||||
|
||||
## 1.2.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 1.2.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Remove results from the `cpp/wrong-type-format-argument` ("Wrong type of arguments to formatting function") query if the argument is the return value of an implicitly declared function.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.2.5
|
||||
lastReleaseVersion: 1.2.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.2.6-dev
|
||||
version: 1.2.7-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -5,31 +5,5 @@
|
||||
|
||||
import cpp as C
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
private module Impl implements InlineExpectationsTestSig {
|
||||
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
|
||||
|
||||
/**
|
||||
* A class representing a line comment in the CPP style.
|
||||
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
|
||||
* include the preceding comment marker (`//`).
|
||||
*/
|
||||
class ExpectationComment extends TExpectationComment {
|
||||
C::CppStyleComment comment;
|
||||
|
||||
ExpectationComment() { this = MkExpectationComment(comment) }
|
||||
|
||||
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
|
||||
string getContents() { result = comment.getContents().suffix(2) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = comment.toString() }
|
||||
|
||||
/** Gets the location of this comment. */
|
||||
Location getLocation() { result = comment.getLocation() }
|
||||
}
|
||||
|
||||
class Location = C::Location;
|
||||
}
|
||||
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import Make<Impl>
|
||||
|
||||
21
cpp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
21
cpp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @kind test-postprocess
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import codeql.util.test.InlineExpectationsTest as T
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import T::TestPostProcessing
|
||||
import T::TestPostProcessing::Make<Impl, Input>
|
||||
|
||||
private module Input implements T::TestPostProcessing::InputSig<Impl> {
|
||||
string getRelativeUrl(Location location) {
|
||||
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
|
||||
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
|
||||
f = location.getFile()
|
||||
|
|
||||
result =
|
||||
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import cpp as C
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
module Impl implements InlineExpectationsTestSig {
|
||||
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
|
||||
|
||||
/**
|
||||
* A class representing a line comment in the CPP style.
|
||||
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
|
||||
* include the preceding comment marker (`//`).
|
||||
*/
|
||||
class ExpectationComment extends TExpectationComment {
|
||||
C::CppStyleComment comment;
|
||||
|
||||
ExpectationComment() { this = MkExpectationComment(comment) }
|
||||
|
||||
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
|
||||
string getContents() { result = comment.getContents().suffix(2) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = comment.toString() }
|
||||
|
||||
/** Gets the location of this comment. */
|
||||
Location getLocation() { result = comment.getLocation() }
|
||||
}
|
||||
|
||||
class Location = C::Location;
|
||||
}
|
||||
@@ -189,3 +189,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -38,3 +38,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -197,3 +197,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -28,3 +28,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @kind graph
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.raw.PrintIR
|
||||
@@ -0,0 +1,7 @@
|
||||
int foo(int i);
|
||||
|
||||
int foo(int i) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
int bar();
|
||||
@@ -0,0 +1,3 @@
|
||||
int foo(int i) {
|
||||
return i;
|
||||
}
|
||||
@@ -100,3 +100,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -37,3 +37,4 @@ identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
speculativeStepAlreadyHasModel
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Critical/SizeCheck.ql
|
||||
query: Critical/SizeCheck.ql
|
||||
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -13,8 +13,8 @@ void free(void *ptr);
|
||||
|
||||
void bad0(void) {
|
||||
|
||||
float *fptr = malloc(3); // BAD -- Too small
|
||||
double *dptr = malloc(5); // BAD -- Too small
|
||||
float *fptr = malloc(3); // $ Alert -- Too small
|
||||
double *dptr = malloc(5); // $ Alert -- Too small
|
||||
free(fptr);
|
||||
free(dptr);
|
||||
}
|
||||
@@ -29,8 +29,8 @@ void good0(void) {
|
||||
|
||||
void bad1(void) {
|
||||
|
||||
float *fptr = malloc(sizeof(short)); // BAD -- Too small
|
||||
double *dptr = malloc(sizeof(float)); // BAD -- Too small
|
||||
float *fptr = malloc(sizeof(short)); // $ Alert -- Too small
|
||||
double *dptr = malloc(sizeof(float)); // $ Alert -- Too small
|
||||
free(fptr);
|
||||
free(dptr);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ typedef union _myUnion
|
||||
|
||||
void test_union() {
|
||||
MyUnion *a = malloc(sizeof(MyUnion)); // GOOD
|
||||
MyUnion *b = malloc(sizeof(MyStruct)); // BAD (too small)
|
||||
MyUnion *b = malloc(sizeof(MyStruct)); // $ Alert (too small)
|
||||
}
|
||||
|
||||
// --- custom allocators ---
|
||||
@@ -66,6 +66,6 @@ void *MyMalloc2(size_t size);
|
||||
|
||||
void customAllocatorTests()
|
||||
{
|
||||
float *fptr1 = MyMalloc1(3); // BAD (too small) [NOT DETECTED]
|
||||
float *fptr2 = MyMalloc2(3); // BAD (too small) [NOT DETECTED]
|
||||
float *fptr1 = MyMalloc1(3); // $ MISSING: BAD (too small)
|
||||
float *fptr2 = MyMalloc2(3); // $ MISSING: BAD (too small)
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Security/CWE/CWE-022/TaintedPath.ql
|
||||
query: Security/CWE/CWE-022/TaintedPath.ql
|
||||
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -5,7 +5,7 @@
|
||||
#define PATH_MAX 4096
|
||||
///// Test code /////
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char** argv) { // $ Source=argv
|
||||
char *userAndFile = argv[2];
|
||||
|
||||
{
|
||||
@@ -14,7 +14,7 @@ int main(int argc, char** argv) {
|
||||
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+");
|
||||
fopen(fileName, "wb+"); // $ Alert=argv
|
||||
}
|
||||
|
||||
{
|
||||
@@ -29,30 +29,30 @@ int main(int argc, char** argv) {
|
||||
|
||||
{
|
||||
char *fileName = argv[1];
|
||||
fopen(fileName, "wb+"); // BAD
|
||||
fopen(fileName, "wb+"); // $ Alert=argv
|
||||
}
|
||||
|
||||
{
|
||||
char fileName[20];
|
||||
scanf("%s", fileName);
|
||||
fopen(fileName, "wb+"); // BAD
|
||||
scanf("%s", fileName); // $ Source=scanf_output1
|
||||
fopen(fileName, "wb+"); // $ Alert=scanf_output1
|
||||
}
|
||||
|
||||
{
|
||||
char *fileName = (char*)malloc(20 * sizeof(char));
|
||||
scanf("%s", fileName);
|
||||
fopen(fileName, "wb+"); // BAD
|
||||
scanf("%s", fileName); // $ Source=scanf_output2
|
||||
fopen(fileName, "wb+"); // $ Alert=scanf_output2
|
||||
}
|
||||
|
||||
{
|
||||
char *tainted = getenv("A_STRING");
|
||||
fopen(tainted, "wb+"); // BAD
|
||||
char *tainted = getenv("A_STRING"); // $ Source=getenv1
|
||||
fopen(tainted, "wb+"); // $ Alert=getenv1
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
strncpy(buffer, getenv("A_STRING"), 1024);
|
||||
fopen(buffer, "wb+"); // BAD
|
||||
strncpy(buffer, getenv("A_STRING"), 1024); // $ Source=getenv2
|
||||
fopen(buffer, "wb+"); // $ Alert=getenv2
|
||||
fopen(buffer, "wb+"); // (we don't want a duplicate result here)
|
||||
}
|
||||
|
||||
@@ -66,14 +66,14 @@ int main(int argc, char** argv) {
|
||||
|
||||
{
|
||||
void readFile(const char *fileName);
|
||||
readFile(argv[1]); // BAD
|
||||
readFile(argv[1]); // $ Alert=argv
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
read(0, buffer, 1024);
|
||||
read(0, buffer, 1024);
|
||||
fopen(buffer, "wb+"); // BAD [duplicated with both sources]
|
||||
read(0, buffer, 1024); // $ Source=read_output1
|
||||
read(0, buffer, 1024); // $ Source=read_output2
|
||||
fopen(buffer, "wb+"); // $ SPURIOUS: Alert=read_output1 $ Alert=read_output2 [duplicated with both sources]
|
||||
}
|
||||
|
||||
{
|
||||
@@ -81,7 +81,7 @@ int main(int argc, char** argv) {
|
||||
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+");
|
||||
fopen(fileBuffer, "wb+"); // $ Alert=argv
|
||||
}
|
||||
|
||||
{
|
||||
@@ -95,7 +95,7 @@ int main(int argc, char** argv) {
|
||||
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+");
|
||||
FILE *file = fopen(fileBuffer, "wb+"); // $ SPURIOUS: Alert=argv
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.28
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.27
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.28
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.27
|
||||
lastReleaseVersion: 1.7.28
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.28-dev
|
||||
version: 1.7.29-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.28
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.27
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.28
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.27
|
||||
lastReleaseVersion: 1.7.28
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.28-dev
|
||||
version: 1.7.29-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 3.1.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The generated .NET 8 runtime models have been updated.
|
||||
|
||||
## 3.0.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The generated .NET 8 runtime models have been updated.
|
||||
5
csharp/ql/lib/change-notes/released/3.1.0.md
Normal file
5
csharp/ql/lib/change-notes/released/3.1.0.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 3.1.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The generated .NET 8 runtime models have been updated.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 3.0.1
|
||||
lastReleaseVersion: 3.1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 3.0.2-dev
|
||||
version: 3.1.1-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -169,3 +169,43 @@ private module Cached {
|
||||
}
|
||||
|
||||
import Cached
|
||||
import SpeculativeTaintFlow
|
||||
|
||||
private module SpeculativeTaintFlow {
|
||||
private import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
|
||||
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as Impl
|
||||
|
||||
private predicate hasTarget(Call call) {
|
||||
exists(Impl::Public::SummarizedCallable sc | sc.getACall() = call)
|
||||
or
|
||||
exists(Impl::Public::NeutralSummaryCallable nc | nc.getACall() = call)
|
||||
or
|
||||
call.getTarget().getUnboundDeclaration() instanceof ExternalFlow::SinkCallable
|
||||
or
|
||||
exists(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.getACall() = call)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
exists(DataFlowCall call, Call srcCall, ArgumentPosition argpos |
|
||||
not exists(viableCallable(call)) and
|
||||
not hasTarget(srcCall) and
|
||||
call.(NonDelegateDataFlowCall).getDispatchCall().getCall() = srcCall and
|
||||
(srcCall instanceof ConstructorInitializer or srcCall instanceof MethodCall) and
|
||||
src.(ArgumentNode).argumentOf(call, argpos) and
|
||||
not src instanceof PostUpdateNodes::ObjectInitializerNode and
|
||||
not src instanceof MallocNode
|
||||
|
|
||||
not argpos.isQualifier() and
|
||||
sink.(PostUpdateNode)
|
||||
.getPreUpdateNode()
|
||||
.(ArgumentNode)
|
||||
.argumentOf(call, any(ArgumentPosition qualpos | qualpos.isQualifier()))
|
||||
or
|
||||
sink.(OutNode).getCall(_) = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 1.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* C#: The method `string.ReplaceLineEndings(string)` is now considered a sanitizer for the `cs/log-forging` query.
|
||||
|
||||
## 1.0.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C#: The method `string.ReplaceLineEndings(string)` is now considered a sanitizer for the `cs/log-forging` query.
|
||||
5
csharp/ql/src/change-notes/released/1.0.11.md
Normal file
5
csharp/ql/src/change-notes/released/1.0.11.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 1.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* C#: The method `string.ReplaceLineEndings(string)` is now considered a sanitizer for the `cs/log-forging` query.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.10
|
||||
lastReleaseVersion: 1.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 1.0.11-dev
|
||||
version: 1.0.12-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Inline expectation tests for CSharp.
|
||||
* Inline expectation tests for C#.
|
||||
* See `shared/util/codeql/util/test/InlineExpectationsTest.qll`
|
||||
*/
|
||||
|
||||
|
||||
21
csharp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
21
csharp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @kind test-postprocess
|
||||
*/
|
||||
|
||||
private import csharp
|
||||
private import codeql.util.test.InlineExpectationsTest as T
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import T::TestPostProcessing
|
||||
import T::TestPostProcessing::Make<Impl, Input>
|
||||
|
||||
private module Input implements T::TestPostProcessing::InputSig<Impl> {
|
||||
string getRelativeUrl(Location location) {
|
||||
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
|
||||
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
|
||||
f = location.getFile()
|
||||
|
|
||||
result =
|
||||
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,3 @@
|
||||
import semmle.code.csharp.dataflow.internal.ExternalFlow
|
||||
import codeql.dataflow.test.ProvenancePathGraph
|
||||
import codeql.dataflow.test.ProvenancePathGraph::TestPostProcessing::TranslateProvenanceResults<interpretModelForTest/2>
|
||||
|
||||
from string relation, int row, int column, string data
|
||||
where results(relation, row, column, data)
|
||||
select relation, row, column, data
|
||||
|
||||
82
csharp/ql/test/TestUtilities/inline-tests/InlineTests.cs
Normal file
82
csharp/ql/test/TestUtilities/inline-tests/InlineTests.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
class C
|
||||
{
|
||||
void Problems()
|
||||
{
|
||||
// correct expectation comment, but only for `problem-query`
|
||||
var x = "Alert"; // $ Alert
|
||||
|
||||
// irrelevant expectation comment, will be ignored
|
||||
x = "Not an alert"; // $ IrrelevantTag
|
||||
|
||||
// incorrect expectation comment
|
||||
x = "Also not an alert"; // $ Alert
|
||||
|
||||
// missing expectation comment, but only for `problem-query`
|
||||
x = "Alert";
|
||||
|
||||
// correct expectation comment
|
||||
x = "Alert"; // $ Alert[problem-query]
|
||||
}
|
||||
|
||||
void PathProblems()
|
||||
{
|
||||
// correct expectation comments, but only for `path-problem-query`
|
||||
var source = "Source"; // $ Source
|
||||
var sink = "Sink"; // $ Sink
|
||||
var x = "Alert:2:1"; // $ Alert
|
||||
|
||||
// incorrect expectation comments
|
||||
source = "Source"; // $ Source
|
||||
sink = "Sink"; // $ Sink
|
||||
x = "Not an alert:2:1"; // $ Alert
|
||||
|
||||
// missing expectation comments, but only for `path-problem-query`
|
||||
source = "Source";
|
||||
sink = "Sink";
|
||||
x = "Alert:2:1";
|
||||
|
||||
// correct expectation comments
|
||||
source = "Source"; // $ Source[path-problem-query]
|
||||
sink = "Sink"; // $ Sink[path-problem-query]
|
||||
x = "Alert:2:1"; // $ Alert[path-problem-query]
|
||||
|
||||
// correct expectation comments; the alert location coincides with the sink location
|
||||
source = "Source"; // $ Source[path-problem-query]
|
||||
x = "Alert:1:0"; // $ Alert[path-problem-query]
|
||||
|
||||
// correct expectation comments; the alert location coincides with the source location
|
||||
sink = "Sink"; // $ Sink[path-problem-query]
|
||||
x = "Alert:0:1"; // $ Alert[path-problem-query]
|
||||
|
||||
// correct expectation comments, using an identifier tag
|
||||
source = "Source"; // $ Source[path-problem-query]=source1
|
||||
sink = "Sink"; // $ Sink[path-problem-query]=source1
|
||||
x = "Alert:2:1"; // $ Alert[path-problem-query]=source1
|
||||
|
||||
// incorrect expectation comment, using wrong identifier tag at the sink
|
||||
source = "Source"; // $ Source[path-problem-query]=source2
|
||||
sink = "Sink"; // $ Sink[path-problem-query]=source1
|
||||
x = "Alert:2:1"; // $ Alert[path-problem-query]=source2
|
||||
|
||||
// incorrect expectation comment, using wrong identifier tag at the alert
|
||||
source = "Source"; // $ Source[path-problem-query]=source3
|
||||
sink = "Sink"; // $ Sink[path-problem-query]=source3
|
||||
x = "Alert:2:1"; // $ Alert[path-problem-query]=source2
|
||||
|
||||
// correct expectation comments, using an identifier tag; the alert location coincides with the sink location
|
||||
source = "Source"; // $ Source[path-problem-query]=source4
|
||||
x = "Alert:1:0"; // $ Alert[path-problem-query]=source4
|
||||
|
||||
// incorrect expectation comments, using an identifier tag; the alert location coincides with the sink location
|
||||
source = "Source"; // $ Source[path-problem-query]=source5
|
||||
x = "Alert:1:0"; // $ Alert[path-problem-query]=source4
|
||||
|
||||
// correct expectation comments, using an identifier tag; the alert location coincides with the source location
|
||||
sink = "Sink"; // $ Sink[path-problem-query]=sink1
|
||||
x = "Alert:0:1"; // $ Alert[path-problem-query]=sink1
|
||||
|
||||
// incorrect expectation comments, using an identifier tag; the alert location coincides with the source location
|
||||
sink = "Sink"; // $ Sink[path-problem-query]=sink2
|
||||
x = "Alert:0:1"; // $ Alert[path-problem-query]=sink1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#select
|
||||
| InlineTests.cs:26:17:26:27 | "Alert:2:1" | InlineTests.cs:24:22:24:29 | "Source" | InlineTests.cs:25:20:25:25 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:36:13:36:23 | "Alert:2:1" | InlineTests.cs:34:18:34:25 | "Source" | InlineTests.cs:35:16:35:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:41:13:41:23 | "Alert:2:1" | InlineTests.cs:39:18:39:25 | "Source" | InlineTests.cs:40:16:40:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:45:13:45:23 | "Alert:1:0" | InlineTests.cs:44:18:44:25 | "Source" | InlineTests.cs:45:13:45:23 | "Alert:1:0" | This is a problem |
|
||||
| InlineTests.cs:49:13:49:23 | "Alert:0:1" | InlineTests.cs:49:13:49:23 | "Alert:0:1" | InlineTests.cs:48:16:48:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:54:13:54:23 | "Alert:2:1" | InlineTests.cs:52:18:52:25 | "Source" | InlineTests.cs:53:16:53:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:59:13:59:23 | "Alert:2:1" | InlineTests.cs:57:18:57:25 | "Source" | InlineTests.cs:58:16:58:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:64:13:64:23 | "Alert:2:1" | InlineTests.cs:62:18:62:25 | "Source" | InlineTests.cs:63:16:63:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:68:13:68:23 | "Alert:1:0" | InlineTests.cs:67:18:67:25 | "Source" | InlineTests.cs:68:13:68:23 | "Alert:1:0" | This is a problem |
|
||||
| InlineTests.cs:72:13:72:23 | "Alert:1:0" | InlineTests.cs:71:18:71:25 | "Source" | InlineTests.cs:72:13:72:23 | "Alert:1:0" | This is a problem |
|
||||
| InlineTests.cs:76:13:76:23 | "Alert:0:1" | InlineTests.cs:76:13:76:23 | "Alert:0:1" | InlineTests.cs:75:16:75:21 | "Sink" | This is a problem |
|
||||
| InlineTests.cs:80:13:80:23 | "Alert:0:1" | InlineTests.cs:80:13:80:23 | "Alert:0:1" | InlineTests.cs:79:16:79:21 | "Sink" | This is a problem |
|
||||
edges
|
||||
testFailures
|
||||
| InlineTests.cs:6:26:6:35 | // ... | Missing result: Alert |
|
||||
| InlineTests.cs:12:34:12:43 | // ... | Missing result: Alert |
|
||||
| InlineTests.cs:29:28:29:38 | // ... | Missing result: Source |
|
||||
| InlineTests.cs:30:24:30:32 | // ... | Missing result: Sink |
|
||||
| InlineTests.cs:31:33:31:42 | // ... | Missing result: Alert |
|
||||
| InlineTests.cs:34:18:34:25 | "Source" | Unexpected result: Source |
|
||||
| InlineTests.cs:35:16:35:21 | "Sink" | Unexpected result: Sink |
|
||||
| InlineTests.cs:36:13:36:23 | InlineTests.cs:34:18:34:25 | Unexpected result: Alert |
|
||||
| InlineTests.cs:58:16:58:21 | "Sink" | Unexpected result: Sink=source2 |
|
||||
| InlineTests.cs:58:24:58:60 | // ... | Missing result: Sink[path-problem-query]=source1 |
|
||||
| InlineTests.cs:64:13:64:23 | InlineTests.cs:62:18:62:25 | Unexpected result: Alert=source3 |
|
||||
| InlineTests.cs:64:26:64:63 | // ... | Missing result: Alert[path-problem-query]=source2 |
|
||||
| InlineTests.cs:72:13:72:23 | "Alert:1:0" | Unexpected result: Alert=source5 |
|
||||
| InlineTests.cs:72:26:72:63 | // ... | Missing result: Alert[path-problem-query]=source4 |
|
||||
| InlineTests.cs:79:16:79:21 | "Sink" | Unexpected result: Sink=sink1 |
|
||||
| InlineTests.cs:79:24:79:58 | // ... | Missing result: Sink[path-problem-query]=sink2 |
|
||||
@@ -0,0 +1,2 @@
|
||||
query: TestUtilities/inline-tests/queries/PathProblemQuery.ql
|
||||
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,9 @@
|
||||
#select
|
||||
| InlineTests.cs:6:17:6:23 | "Alert" | This is a problem |
|
||||
| InlineTests.cs:15:13:15:19 | "Alert" | This is a problem |
|
||||
| InlineTests.cs:18:13:18:19 | "Alert" | This is a problem |
|
||||
testFailures
|
||||
| InlineTests.cs:12:34:12:43 | // ... | Missing result: Alert |
|
||||
| InlineTests.cs:15:13:15:19 | This is a problem | Unexpected result: Alert |
|
||||
| InlineTests.cs:26:30:26:39 | // ... | Missing result: Alert |
|
||||
| InlineTests.cs:31:33:31:42 | // ... | Missing result: Alert |
|
||||
@@ -0,0 +1,2 @@
|
||||
query: TestUtilities/inline-tests/queries/ProblemQuery.ql
|
||||
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
edges
|
||||
#select
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
* @id path-problem-query
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
query predicate edges(StringLiteral sl1, StringLiteral sl2) { none() }
|
||||
|
||||
from StringLiteral alert, StringLiteral source, StringLiteral sink
|
||||
where
|
||||
exists(string regexp, int sourceOffset, int sinkOffset | regexp = "Alert:([0-9]+):([0-9]+)" |
|
||||
sourceOffset = alert.getValue().regexpCapture(regexp, 1).toInt() and
|
||||
sinkOffset = alert.getValue().regexpCapture(regexp, 2).toInt() and
|
||||
source.getLocation().getStartLine() = alert.getLocation().getStartLine() - sourceOffset and
|
||||
sink.getLocation().getStartLine() = alert.getLocation().getStartLine() - sinkOffset
|
||||
)
|
||||
select alert, source, sink, "This is a problem"
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @kind problem
|
||||
* @id problem-query
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from StringLiteral sl
|
||||
where sl.getValue() = "Alert"
|
||||
select sl, "This is a problem"
|
||||
@@ -30,7 +30,7 @@ using dotnetweb;
|
||||
#line 3 "Index.cshtml"
|
||||
|
||||
ViewData["Title"] = "ASP.NET Core";
|
||||
var message = Request.Query["m"];
|
||||
var message = Request.Query["m"]; // $ Source=message
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
@@ -38,7 +38,7 @@ using dotnetweb;
|
||||
WriteLiteral("<div class=\"cli\">\n <div class=\"cli-example\"> \n");
|
||||
#nullable restore
|
||||
#line 14 "Index.cshtml"
|
||||
Write(Html.Raw(message)); // BAD
|
||||
Write(Html.Raw(message)); // $ Alert=message
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
| Index.cshtml:14:16:14:22 | call to operator implicit conversion | Index.cshtml:5:19:5:31 | access to property Query : IQueryCollection | Index.cshtml:14:16:14:22 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript: Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method. | Index.cshtml:5:19:5:31 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNet.cs:26:30:26:34 | access to local variable sayHi | XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | XSSAspNet.cs:26:30:26:34 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteral() method. | XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | User-provided value |
|
||||
| XSSAspNet.cs:36:40:36:44 | access to local variable sayHi | XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | XSSAspNet.cs:36:40:36:44 | access to local variable sayHi | $@ flows to here and is written to HTML or JavaScript: System.Web.WebPages.WebPage.WriteLiteralTo() method. | XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | User-provided value |
|
||||
| XSSAspNet.cs:43:28:43:55 | access to indexer | XSSAspNet.cs:43:28:43:46 | access to property QueryString : NameValueCollection | XSSAspNet.cs:43:28:43:55 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNet.cs:43:28:43:46 | access to property QueryString : NameValueCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:21:52:21:76 | call to operator implicit conversion | XSSAspNetCore.cs:21:52:21:64 | access to property Query : IQueryCollection | XSSAspNetCore.cs:21:52:21:76 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:21:52:21:64 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:44:51:44:53 | access to parameter foo | XSSAspNetCore.cs:40:56:40:58 | foo : String | XSSAspNetCore.cs:44:51:44:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:40:56:40:58 | foo : String | User-provided value |
|
||||
| XSSAspNetCore.cs:51:43:51:67 | access to property Value | XSSAspNetCore.cs:51:43:51:67 | access to property Value | XSSAspNetCore.cs:51:43:51:67 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:51:43:51:67 | access to property Value | User-provided value |
|
||||
| XSSAspNetCore.cs:58:43:58:73 | call to method ToString | XSSAspNetCore.cs:58:43:58:55 | access to property Query : IQueryCollection | XSSAspNetCore.cs:58:43:58:73 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:58:43:58:55 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:61:44:61:66 | access to indexer | XSSAspNetCore.cs:61:44:61:56 | access to property Query : IQueryCollection | XSSAspNetCore.cs:61:44:61:66 | access to indexer | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:61:44:61:56 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | User-provided value |
|
||||
| XSSAspNetCore.cs:72:51:72:72 | call to operator implicit conversion | XSSAspNetCore.cs:72:51:72:65 | access to property Headers : IHeaderDictionary | XSSAspNetCore.cs:72:51:72:72 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:72:51:72:65 | access to property Headers : IHeaderDictionary | User-provided value |
|
||||
| XSSAspNet.cs:44:28:44:33 | access to local variable sayHi2 | XSSAspNet.cs:43:26:43:44 | access to property QueryString : NameValueCollection | XSSAspNet.cs:44:28:44:33 | access to local variable sayHi2 | $@ flows to here and is written to HTML or JavaScript. | XSSAspNet.cs:43:26:43:44 | access to property QueryString : NameValueCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:22:52:22:57 | call to operator implicit conversion | XSSAspNetCore.cs:21:26:21:38 | access to property Query : IQueryCollection | XSSAspNetCore.cs:22:52:22:57 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:21:26:21:38 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | XSSAspNetCore.cs:41:56:41:58 | foo : String | XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:41:56:41:58 | foo : String | User-provided value |
|
||||
| XSSAspNetCore.cs:53:43:53:46 | access to local variable req2 | XSSAspNetCore.cs:52:24:52:48 | access to property Value : String | XSSAspNetCore.cs:53:43:53:46 | access to local variable req2 | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:52:24:52:48 | access to property Value : String | User-provided value |
|
||||
| XSSAspNetCore.cs:61:43:61:46 | access to local variable req3 | XSSAspNetCore.cs:60:24:60:36 | access to property Query : IQueryCollection | XSSAspNetCore.cs:61:43:61:46 | access to local variable req3 | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:60:24:60:36 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:65:44:65:47 | access to local variable req4 | XSSAspNetCore.cs:64:24:64:36 | access to property Query : IQueryCollection | XSSAspNetCore.cs:65:44:65:47 | access to local variable req4 | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:64:24:64:36 | access to property Query : IQueryCollection | User-provided value |
|
||||
| XSSAspNetCore.cs:74:43:74:44 | access to local variable ct | XSSAspNetCore.cs:73:22:73:40 | access to property ContentType : String | XSSAspNetCore.cs:74:43:74:44 | access to local variable ct | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:73:22:73:40 | access to property ContentType : String | User-provided value |
|
||||
| XSSAspNetCore.cs:78:51:78:56 | call to operator implicit conversion | XSSAspNetCore.cs:77:26:77:40 | access to property Headers : IHeaderDictionary | XSSAspNetCore.cs:78:51:78:56 | call to operator implicit conversion | $@ flows to here and is written to HTML or JavaScript. | XSSAspNetCore.cs:77:26:77:40 | access to property Headers : IHeaderDictionary | User-provided value |
|
||||
edges
|
||||
| Index.cshtml:5:9:5:15 | access to local variable message : StringValues | Index.cshtml:14:16:14:22 | call to operator implicit conversion | provenance | |
|
||||
| Index.cshtml:5:19:5:31 | access to property Query : IQueryCollection | Index.cshtml:5:9:5:15 | access to local variable message : StringValues | provenance | |
|
||||
@@ -18,17 +18,29 @@ edges
|
||||
| XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | XSSAspNet.cs:19:17:19:21 | access to local variable sayHi : String | provenance | |
|
||||
| XSSAspNet.cs:19:25:19:43 | access to property QueryString : NameValueCollection | XSSAspNet.cs:19:25:19:52 | access to indexer : String | provenance | MaD:3 |
|
||||
| XSSAspNet.cs:19:25:19:52 | access to indexer : String | XSSAspNet.cs:19:17:19:21 | access to local variable sayHi : String | provenance | |
|
||||
| XSSAspNet.cs:43:28:43:46 | access to property QueryString : NameValueCollection | XSSAspNet.cs:43:28:43:55 | access to indexer | provenance | |
|
||||
| XSSAspNet.cs:43:28:43:46 | access to property QueryString : NameValueCollection | XSSAspNet.cs:43:28:43:55 | access to indexer | provenance | MaD:3 |
|
||||
| XSSAspNetCore.cs:21:52:21:64 | access to property Query : IQueryCollection | XSSAspNetCore.cs:21:52:21:76 | call to operator implicit conversion | provenance | |
|
||||
| XSSAspNetCore.cs:40:56:40:58 | foo : String | XSSAspNetCore.cs:44:51:44:53 | access to parameter foo | provenance | |
|
||||
| XSSAspNetCore.cs:58:43:58:55 | access to property Query : IQueryCollection | XSSAspNetCore.cs:58:43:58:62 | access to indexer : StringValues | provenance | |
|
||||
| XSSAspNetCore.cs:58:43:58:62 | access to indexer : StringValues | XSSAspNetCore.cs:58:43:58:73 | call to method ToString | provenance | MaD:1 |
|
||||
| XSSAspNetCore.cs:61:44:61:56 | access to property Query : IQueryCollection | XSSAspNetCore.cs:61:44:61:63 | access to indexer : StringValues | provenance | |
|
||||
| XSSAspNetCore.cs:61:44:61:56 | access to property Query : IQueryCollection | XSSAspNetCore.cs:61:44:61:66 | access to indexer | provenance | |
|
||||
| XSSAspNetCore.cs:61:44:61:63 | access to indexer : StringValues | XSSAspNetCore.cs:61:44:61:66 | access to indexer | provenance | |
|
||||
| XSSAspNetCore.cs:61:44:61:63 | access to indexer : StringValues | XSSAspNetCore.cs:61:44:61:66 | access to indexer | provenance | MaD:2 |
|
||||
| XSSAspNetCore.cs:72:51:72:65 | access to property Headers : IHeaderDictionary | XSSAspNetCore.cs:72:51:72:72 | call to operator implicit conversion | provenance | |
|
||||
| XSSAspNet.cs:43:17:43:22 | access to local variable sayHi2 : String | XSSAspNet.cs:44:28:44:33 | access to local variable sayHi2 | provenance | |
|
||||
| XSSAspNet.cs:43:26:43:44 | access to property QueryString : NameValueCollection | XSSAspNet.cs:43:17:43:22 | access to local variable sayHi2 : String | provenance | |
|
||||
| XSSAspNet.cs:43:26:43:44 | access to property QueryString : NameValueCollection | XSSAspNet.cs:43:26:43:53 | access to indexer : String | provenance | MaD:3 |
|
||||
| XSSAspNet.cs:43:26:43:53 | access to indexer : String | XSSAspNet.cs:43:17:43:22 | access to local variable sayHi2 : String | provenance | |
|
||||
| XSSAspNetCore.cs:21:17:21:22 | access to local variable source : StringValues | XSSAspNetCore.cs:22:52:22:57 | call to operator implicit conversion | provenance | |
|
||||
| XSSAspNetCore.cs:21:26:21:38 | access to property Query : IQueryCollection | XSSAspNetCore.cs:21:17:21:22 | access to local variable source : StringValues | provenance | |
|
||||
| XSSAspNetCore.cs:41:56:41:58 | foo : String | XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | provenance | |
|
||||
| XSSAspNetCore.cs:52:17:52:20 | access to local variable req2 : String | XSSAspNetCore.cs:53:43:53:46 | access to local variable req2 | provenance | |
|
||||
| XSSAspNetCore.cs:52:24:52:48 | access to property Value : String | XSSAspNetCore.cs:52:17:52:20 | access to local variable req2 : String | provenance | |
|
||||
| XSSAspNetCore.cs:60:17:60:20 | access to local variable req3 : String | XSSAspNetCore.cs:61:43:61:46 | access to local variable req3 | provenance | |
|
||||
| XSSAspNetCore.cs:60:24:60:36 | access to property Query : IQueryCollection | XSSAspNetCore.cs:60:24:60:43 | access to indexer : StringValues | provenance | |
|
||||
| XSSAspNetCore.cs:60:24:60:43 | access to indexer : StringValues | XSSAspNetCore.cs:60:24:60:54 | call to method ToString : String | provenance | MaD:1 |
|
||||
| XSSAspNetCore.cs:60:24:60:54 | call to method ToString : String | XSSAspNetCore.cs:60:17:60:20 | access to local variable req3 : String | provenance | |
|
||||
| XSSAspNetCore.cs:64:17:64:20 | access to local variable req4 : String | XSSAspNetCore.cs:65:44:65:47 | access to local variable req4 | provenance | |
|
||||
| XSSAspNetCore.cs:64:24:64:36 | access to property Query : IQueryCollection | XSSAspNetCore.cs:64:17:64:20 | access to local variable req4 : String | provenance | |
|
||||
| XSSAspNetCore.cs:64:24:64:36 | access to property Query : IQueryCollection | XSSAspNetCore.cs:64:24:64:43 | access to indexer : StringValues | provenance | |
|
||||
| XSSAspNetCore.cs:64:24:64:43 | access to indexer : StringValues | XSSAspNetCore.cs:64:17:64:20 | access to local variable req4 : String | provenance | |
|
||||
| XSSAspNetCore.cs:64:24:64:43 | access to indexer : StringValues | XSSAspNetCore.cs:64:24:64:46 | access to indexer : String | provenance | MaD:2 |
|
||||
| XSSAspNetCore.cs:64:24:64:46 | access to indexer : String | XSSAspNetCore.cs:64:17:64:20 | access to local variable req4 : String | provenance | |
|
||||
| XSSAspNetCore.cs:73:17:73:18 | access to local variable ct : String | XSSAspNetCore.cs:74:43:74:44 | access to local variable ct | provenance | |
|
||||
| XSSAspNetCore.cs:73:22:73:40 | access to property ContentType : String | XSSAspNetCore.cs:73:17:73:18 | access to local variable ct : String | provenance | |
|
||||
| XSSAspNetCore.cs:77:17:77:22 | access to local variable header : StringValues | XSSAspNetCore.cs:78:51:78:56 | call to operator implicit conversion | provenance | |
|
||||
| XSSAspNetCore.cs:77:26:77:40 | access to property Headers : IHeaderDictionary | XSSAspNetCore.cs:77:17:77:22 | access to local variable header : StringValues | provenance | |
|
||||
models
|
||||
| 1 | Summary: Microsoft.Extensions.Primitives; StringValues; false; ToString; (); ; Argument[this]; ReturnValue; taint; manual |
|
||||
| 2 | Summary: Microsoft.Extensions.Primitives; StringValues; false; get_Item; (System.Int32); ; Argument[this]; ReturnValue; taint; manual |
|
||||
@@ -42,20 +54,32 @@ nodes
|
||||
| XSSAspNet.cs:19:25:19:52 | access to indexer : String | semmle.label | access to indexer : String |
|
||||
| XSSAspNet.cs:26:30:26:34 | access to local variable sayHi | semmle.label | access to local variable sayHi |
|
||||
| XSSAspNet.cs:36:40:36:44 | access to local variable sayHi | semmle.label | access to local variable sayHi |
|
||||
| XSSAspNet.cs:43:28:43:46 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
|
||||
| XSSAspNet.cs:43:28:43:55 | access to indexer | semmle.label | access to indexer |
|
||||
| XSSAspNetCore.cs:21:52:21:64 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:21:52:21:76 | call to operator implicit conversion | semmle.label | call to operator implicit conversion |
|
||||
| XSSAspNetCore.cs:40:56:40:58 | foo : String | semmle.label | foo : String |
|
||||
| XSSAspNetCore.cs:44:51:44:53 | access to parameter foo | semmle.label | access to parameter foo |
|
||||
| XSSAspNetCore.cs:51:43:51:67 | access to property Value | semmle.label | access to property Value |
|
||||
| XSSAspNetCore.cs:58:43:58:55 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:58:43:58:62 | access to indexer : StringValues | semmle.label | access to indexer : StringValues |
|
||||
| XSSAspNetCore.cs:58:43:58:73 | call to method ToString | semmle.label | call to method ToString |
|
||||
| XSSAspNetCore.cs:61:44:61:56 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:61:44:61:63 | access to indexer : StringValues | semmle.label | access to indexer : StringValues |
|
||||
| XSSAspNetCore.cs:61:44:61:66 | access to indexer | semmle.label | access to indexer |
|
||||
| XSSAspNetCore.cs:69:43:69:61 | access to property ContentType | semmle.label | access to property ContentType |
|
||||
| XSSAspNetCore.cs:72:51:72:65 | access to property Headers : IHeaderDictionary | semmle.label | access to property Headers : IHeaderDictionary |
|
||||
| XSSAspNetCore.cs:72:51:72:72 | call to operator implicit conversion | semmle.label | call to operator implicit conversion |
|
||||
| XSSAspNet.cs:43:17:43:22 | access to local variable sayHi2 : String | semmle.label | access to local variable sayHi2 : String |
|
||||
| XSSAspNet.cs:43:26:43:44 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
|
||||
| XSSAspNet.cs:43:26:43:53 | access to indexer : String | semmle.label | access to indexer : String |
|
||||
| XSSAspNet.cs:44:28:44:33 | access to local variable sayHi2 | semmle.label | access to local variable sayHi2 |
|
||||
| XSSAspNetCore.cs:21:17:21:22 | access to local variable source : StringValues | semmle.label | access to local variable source : StringValues |
|
||||
| XSSAspNetCore.cs:21:26:21:38 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:22:52:22:57 | call to operator implicit conversion | semmle.label | call to operator implicit conversion |
|
||||
| XSSAspNetCore.cs:41:56:41:58 | foo : String | semmle.label | foo : String |
|
||||
| XSSAspNetCore.cs:45:51:45:53 | access to parameter foo | semmle.label | access to parameter foo |
|
||||
| XSSAspNetCore.cs:52:17:52:20 | access to local variable req2 : String | semmle.label | access to local variable req2 : String |
|
||||
| XSSAspNetCore.cs:52:24:52:48 | access to property Value : String | semmle.label | access to property Value : String |
|
||||
| XSSAspNetCore.cs:53:43:53:46 | access to local variable req2 | semmle.label | access to local variable req2 |
|
||||
| XSSAspNetCore.cs:60:17:60:20 | access to local variable req3 : String | semmle.label | access to local variable req3 : String |
|
||||
| XSSAspNetCore.cs:60:24:60:36 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:60:24:60:43 | access to indexer : StringValues | semmle.label | access to indexer : StringValues |
|
||||
| XSSAspNetCore.cs:60:24:60:54 | call to method ToString : String | semmle.label | call to method ToString : String |
|
||||
| XSSAspNetCore.cs:61:43:61:46 | access to local variable req3 | semmle.label | access to local variable req3 |
|
||||
| XSSAspNetCore.cs:64:17:64:20 | access to local variable req4 : String | semmle.label | access to local variable req4 : String |
|
||||
| XSSAspNetCore.cs:64:24:64:36 | access to property Query : IQueryCollection | semmle.label | access to property Query : IQueryCollection |
|
||||
| XSSAspNetCore.cs:64:24:64:43 | access to indexer : StringValues | semmle.label | access to indexer : StringValues |
|
||||
| XSSAspNetCore.cs:64:24:64:46 | access to indexer : String | semmle.label | access to indexer : String |
|
||||
| XSSAspNetCore.cs:65:44:65:47 | access to local variable req4 | semmle.label | access to local variable req4 |
|
||||
| XSSAspNetCore.cs:73:17:73:18 | access to local variable ct : String | semmle.label | access to local variable ct : String |
|
||||
| XSSAspNetCore.cs:73:22:73:40 | access to property ContentType : String | semmle.label | access to property ContentType : String |
|
||||
| XSSAspNetCore.cs:74:43:74:44 | access to local variable ct | semmle.label | access to local variable ct |
|
||||
| XSSAspNetCore.cs:77:17:77:22 | access to local variable header : StringValues | semmle.label | access to local variable header : StringValues |
|
||||
| XSSAspNetCore.cs:77:26:77:40 | access to property Headers : IHeaderDictionary | semmle.label | access to property Headers : IHeaderDictionary |
|
||||
| XSSAspNetCore.cs:78:51:78:56 | call to operator implicit conversion | semmle.label | call to operator implicit conversion |
|
||||
subpaths
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
query: Security Features/CWE-079/XSS.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess:
|
||||
- TestUtilities/PrettyPrintModels.ql
|
||||
- TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -16,14 +16,14 @@ namespace ASP
|
||||
{
|
||||
Layout = "~/_SiteLayout.cshtml";
|
||||
Page.Title = "Contact";
|
||||
var sayHi = Request.QueryString["sayHi"];
|
||||
var sayHi = Request.QueryString["sayHi"]; // $ Source=sayHi
|
||||
if (sayHi.IsEmpty())
|
||||
{
|
||||
WriteLiteral("<script>alert(\"XSS via WriteLiteral\")</script>"); // GOOD: hard-coded, not user input
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLiteral(sayHi); // BAD: user input flows to HTML unencoded
|
||||
WriteLiteral(sayHi); // $ Alert=sayHi
|
||||
WriteLiteral(HttpUtility.HtmlEncode(sayHi)); // Good: user input is encoded before it flows to HTML
|
||||
}
|
||||
|
||||
@@ -33,15 +33,16 @@ namespace ASP
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLiteralTo(Output, sayHi); // BAD: user input flows to HTML unencoded
|
||||
WriteLiteralTo(Output, sayHi); // $ Alert=sayHi
|
||||
WriteLiteralTo(Output, Html.Encode(sayHi)); // Good: user input is encoded before it flows to HTML
|
||||
}
|
||||
|
||||
BeginContext("~/Views/Home/Contact.cshtml", 288, 32, false);
|
||||
|
||||
Write(Html.Raw("<script>alert(\"XSS via Html.Raw()\")</script>")); // GOOD: hard-coded, not user input
|
||||
Write(Html.Raw(Request.QueryString["sayHi"])); // BAD: user input flows to HTML unencoded
|
||||
Write(Html.Raw(HttpContext.Current.Server.HtmlEncode(Request.QueryString["sayHi"]))); // Good: user input is encoded before it flows to HTML
|
||||
var sayHi2 = Request.QueryString["sayHi"]; // $ Source=sayHi2
|
||||
Write(Html.Raw(sayHi2)); // $ Alert=sayHi2
|
||||
Write(Html.Raw(HttpContext.Current.Server.HtmlEncode(sayHi2))); // Good: user input is encoded before it flows to HTML
|
||||
EndContext("~/Views/Home/Contact.cshtml", 288, 32, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace Testing.Controllers
|
||||
{
|
||||
// BAD: flow of content type to.
|
||||
var v = new ViewResult();
|
||||
v.ViewData["BadData"] = new HtmlString(Request.Query["Bad data"]);
|
||||
var source = Request.Query["Bad data"]; // $ Source=req1
|
||||
v.ViewData["BadData"] = new HtmlString(source); // $ Alert=req1
|
||||
|
||||
StringValues vOut;
|
||||
Request.Query.TryGetValue("Foo", out vOut);
|
||||
@@ -37,28 +38,31 @@ namespace Testing.Controllers
|
||||
|
||||
[HttpPost("Test")]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult Submit([FromQuery] string foo)
|
||||
public IActionResult Submit([FromQuery] string foo) // $ Source=foo
|
||||
{
|
||||
var view = new ViewResult();
|
||||
//BAD: flow of submitted value to view in HtmlString.
|
||||
view.ViewData["FOO"] = new HtmlString(foo);
|
||||
view.ViewData["FOO"] = new HtmlString(foo); // $ Alert=foo
|
||||
return view;
|
||||
}
|
||||
|
||||
public IActionResult IndexToModel()
|
||||
{
|
||||
//BAD: flow of submitted value to view in HtmlString.
|
||||
HtmlString v = new HtmlString(Request.QueryString.Value);
|
||||
var req2 = Request.QueryString.Value; // $ Source=req2
|
||||
HtmlString v = new HtmlString(req2); // $ Alert=req2
|
||||
return View(new HomeViewModel() { Message = "Message from Index", Description = v });
|
||||
}
|
||||
|
||||
public IActionResult About()
|
||||
{
|
||||
//BAD: flow of submitted value to view in HtmlString.
|
||||
HtmlString v = new HtmlString(Request.Query["Foo"].ToString());
|
||||
var req3 = Request.Query["Foo"].ToString(); // $ Source=req3
|
||||
HtmlString v = new HtmlString(req3); // $ Alert=req3
|
||||
|
||||
//BAD: flow of submitted value to view in HtmlString.
|
||||
HtmlString v1 = new HtmlString(Request.Query["Foo"][0]);
|
||||
var req4 = Request.Query["Foo"][0]; // $ Source=req4
|
||||
HtmlString v1 = new HtmlString(req4); // $ Alert=req4
|
||||
|
||||
return View(new HomeViewModel() { Message = "Message from About", Description = v });
|
||||
}
|
||||
@@ -66,10 +70,12 @@ namespace Testing.Controllers
|
||||
public IActionResult Contact()
|
||||
{
|
||||
//BAD: flow of user content type to view in HtmlString.
|
||||
HtmlString v = new HtmlString(Request.ContentType);
|
||||
var ct = Request.ContentType; // $ Source=ct
|
||||
HtmlString v = new HtmlString(ct); // $ Alert=ct
|
||||
|
||||
//BAD: flow of headers to view in HtmlString.
|
||||
HtmlString v1 = new HtmlString(value: Request.Headers["Foo"]);
|
||||
var header = Request.Headers["Foo"]; // $ Source=header
|
||||
HtmlString v1 = new HtmlString(value: header); // $ Alert=header
|
||||
|
||||
return View(new HomeViewModel() { Message = "Message from Contact", Description = v });
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ class UnusedLabelTest
|
||||
void F1()
|
||||
{
|
||||
goto a;
|
||||
a: // GOOD
|
||||
a: // GOOD
|
||||
;
|
||||
}
|
||||
|
||||
void F2()
|
||||
{
|
||||
a: // BAD
|
||||
a: // $ Alert
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
| UnusedLabel.cs:12:9:12:9 | a: | This label is not used. |
|
||||
| UnusedLabel.cs:12:5:12:5 | a: | This label is not used. |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Useless code/UnusedLabel.ql
|
||||
query: Useless code/UnusedLabel.ql
|
||||
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
|
||||
@@ -506,7 +506,7 @@ Kinds
|
||||
Source kinds
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- **remote**: A generic source of remote flow. Most taint-tracking queries will use such a source. Currently this is the only supported source kind.
|
||||
See documentation below for :ref:`Threat models <threat-models-javascript>`.
|
||||
|
||||
Sink kinds
|
||||
~~~~~~~~~~
|
||||
@@ -529,3 +529,10 @@ Summary kinds
|
||||
|
||||
- **taint**: A summary that propagates taint. This means the output is not necessarily equal to the input, but it was derived from the input in an unrestrictive way. An attacker who controls the input will have significant control over the output as well.
|
||||
- **value**: A summary that preserves the value of the input or creates a copy of the input such that all of its object properties are preserved.
|
||||
|
||||
.. _threat-models-javascript:
|
||||
|
||||
Threat models
|
||||
-------------
|
||||
|
||||
.. include:: ../reusables/threat-model-description.rst
|
||||
|
||||
@@ -55,7 +55,7 @@ New Queries
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The :code:`py/cors-misconfiguration-with-credentials` query, which finds insecure CORS middleware configurations.
|
||||
* The experimental :code:`py/cors-misconfiguration-with-credentials` query, which finds insecure CORS middleware configurations.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
.. _codeql-cli-2.19.2:
|
||||
|
||||
==========================
|
||||
CodeQL 2.19.2 (2024-10-21)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.19.2 runs a total of 427 security queries when configured with the Default suite (covering 164 CWE). The Extended suite enables an additional 128 queries (covering 34 more CWE). 1 security query has been added with this release.
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Potentially Breaking Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* The Python extractor will no longer extract the standard library by default, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. It will for a while be possible to force extraction of the standard library by setting the environment variable :code:`CODEQL_EXTRACTOR_PYTHON_EXTRACT_STDLIB` to :code:`1`.
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
* The 2.19.1 release contained a bug in the query evaluator that under rare conditions could lead to wrong alerts or resource exhaustion. Although we have never seen the problem outside of internal testing, we encourage users on 2.19.1 to upgrade to 2.19.2.
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* The database relation :code:`sourceLocationPrefix` is changed for databases created with
|
||||
:code:`codeql test run`. Instead of containing the path of the enclosing qlpack, it now contains the actual path of the test, similar to if one had run :code:`codeql database create` on the test folder. For example, for a test such as
|
||||
:code:`<checkout>/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.qlref` we now populate
|
||||
:code:`sourceLocationPrefix` with :code:`<checkout>/cpp/ql/test/query-tests/Security/CWE/CWE-611/` instead of :code:`<checkout>/cpp/ql/test/`. This change typically impacts calls to
|
||||
:code:`File.getRelativePath()`, and may as a result change the expected test output.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`cpp/unclear-array-index-validation` ("Unclear validation of array index") query has been improved to reduce false positives and increase true positives.
|
||||
* Fixed false positives in the :code:`cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
|
||||
* The :code:`cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
|
||||
* The :code:`cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.
|
||||
|
||||
Ruby
|
||||
""""
|
||||
|
||||
* The :code:`rb/diagnostics/extraction-errors` diagnostic query has been split into :code:`rb/diagnostics/extraction-errors` and :code:`rb/diagnostics/extraction-warnings`, counting extraction errors and warnings respectively.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added taint flow model for :code:`fopen` and related functions.
|
||||
* The :code:`SimpleRangeAnalysis` library (:code:`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to :code:`fgetc` and :code:`getc`.
|
||||
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* Added member predicates :code:`StructTag.hasOwnFieldWithTag` and :code:`Field.getTag`, which enable CodeQL queries to examine struct field tags.
|
||||
* Added member predicate :code:`InterfaceType.hasPrivateMethodWithQualifiedName`, which enables CodeQL queries to distinguish interfaces with matching non-exported method names that are declared in different packages, and are therefore incompatible.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* Modelled that :code:`re.finditer` returns an iterable of :code:`re.Match` objects. This is now understood by the API graph in many cases.
|
||||
* Type tracking, and hence the API graph, is now able to correctly trace through comprehensions.
|
||||
* More precise modelling of the dataflow through comprehensions. In particular, captured variables are now handled correctly.
|
||||
* Dataflow out of yield is added, allowing proper tracing through generators.
|
||||
* Added several models of standard library functions and classes, in anticipation of no longer extracting the standard library in a future release.
|
||||
|
||||
Ruby
|
||||
""""
|
||||
|
||||
* The :code:`ExtractionError` class has been split into :code:`ExtractionError` and :code:`ExtractionWarning`, reporting extraction errors and warnings respectively.
|
||||
@@ -11,6 +11,7 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.19.2
|
||||
codeql-cli-2.19.1
|
||||
codeql-cli-2.19.0
|
||||
codeql-cli-2.18.4
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
Note
|
||||
|
||||
Threat models are currently in beta and subject to change. During the beta, threat models are supported only by Java, C# and Python analysis.
|
||||
Threat models are currently in beta and subject to change. During the beta, threat models are supported only by Java, C#, Python and JavaScript/TypeScript analysis.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.0.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.0.11
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.10
|
||||
lastReleaseVersion: 1.0.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql-go-consistency-queries
|
||||
version: 1.0.11-dev
|
||||
version: 1.0.12-dev
|
||||
groups:
|
||||
- go
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 2.1.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The AST viewer now shows type parameter declarations in the correct place in the AST.
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 2.1.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The AST viewer now shows type parameter declarations in the correct place in the AST.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.1.1
|
||||
lastReleaseVersion: 2.1.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/go-all
|
||||
version: 2.1.2-dev
|
||||
version: 2.1.3-dev
|
||||
groups: go
|
||||
dbscheme: go.dbscheme
|
||||
extractor: go
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user