Merge branch 'main' into pin

This commit is contained in:
Geoffrey White
2025-05-21 17:24:00 +01:00
219 changed files with 9990 additions and 2103 deletions

View File

@@ -26,9 +26,8 @@ jobs:
uses: ./go/actions/test
test-win:
if: github.repository_owner == 'github'
name: Test Windows
runs-on: windows-latest-xl
runs-on: windows-latest
steps:
- name: Check out code
uses: actions/checkout@v4

1
.gitignore vendored
View File

@@ -62,6 +62,7 @@ node_modules/
# Temporary folders for working with generated models
.model-temp
/mad-generation-build
# bazel-built in-tree extractor packs
/*/extractor-pack

View File

@@ -10,6 +10,7 @@ members = [
"rust/ast-generator",
"rust/autobuild",
]
exclude = ["mad-generation-build"]
[patch.crates-io]
# patch for build script bug preventing bazel build

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Fixed a problem where `asExpr()` on `DataFlow::Node` would never return `ArrayAggregateLiteral`s.

View File

@@ -0,0 +1,9 @@
---
category: breaking
---
* Deleted the deprecated `userInputArgument` predicate and its convenience accessor from the `Security.qll`.
* Deleted the deprecated `userInputReturned` predicate and its convenience accessor from the `Security.qll`.
* Deleted the deprecated `userInputReturn` predicate from the `Security.qll`.
* Deleted the deprecated `isUserInput` predicate and its convenience accessor from the `Security.qll`.
* Deleted the deprecated `userInputArgument` predicate from the `SecurityOptions.qll`.
* Deleted the deprecated `userInputReturned` predicate from the `SecurityOptions.qll`.

View File

@@ -1,7 +1,8 @@
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private import experimental.quantum.Language
private import semmle.code.cpp.dataflow.new.DataFlow
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
/**
* Traces 'known algorithms' to AVCs, specifically

View File

@@ -1,9 +1,10 @@
import cpp
import experimental.quantum.Language
import OpenSSLAlgorithmInstanceBase
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
import AlgToAVCFlow
private import experimental.quantum.Language
private import OpenSSLAlgorithmInstanceBase
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import AlgToAVCFlow
/**
* Given a `KnownOpenSSLBlockModeAlgorithmConstant`, converts this to a block family type.

View File

@@ -1,12 +1,13 @@
import cpp
import experimental.quantum.Language
import KnownAlgorithmConstants
import Crypto::KeyOpAlg as KeyOpAlg
import OpenSSLAlgorithmInstanceBase
import PaddingAlgorithmInstance
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import AlgToAVCFlow
import BlockAlgorithmInstance
private import experimental.quantum.Language
private import KnownAlgorithmConstants
private import Crypto::KeyOpAlg as KeyOpAlg
private import OpenSSLAlgorithmInstanceBase
private import PaddingAlgorithmInstance
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
private import AlgToAVCFlow
private import BlockAlgorithmInstance
/**
* Given a `KnownOpenSSLCipherAlgorithmConstant`, converts this to a cipher family type.

View File

@@ -0,0 +1,46 @@
import cpp
private import experimental.quantum.Language
private import KnownAlgorithmConstants
private import OpenSSLAlgorithmInstanceBase
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
private import AlgToAVCFlow
class KnownOpenSSLEllipticCurveConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
Crypto::EllipticCurveInstance instanceof KnownOpenSSLEllipticCurveAlgorithmConstant
{
OpenSSLAlgorithmValueConsumer getterCall;
KnownOpenSSLEllipticCurveConstantAlgorithmInstance() {
// Two possibilities:
// 1) The source is a literal and flows to a getter, then we know we have an instance
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
// Possibility 1:
this instanceof Literal and
exists(DataFlow::Node src, DataFlow::Node sink |
// Sink is an argument to a CipherGetterCall
sink = getterCall.getInputNode() and
// Source is `this`
src.asExpr() = this and
// This traces to a getter
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
)
or
// Possibility 2:
this instanceof DirectAlgorithmValueConsumer and getterCall = this
}
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
override string getRawEllipticCurveName() { result = this.(Literal).getValue().toString() }
override Crypto::TEllipticCurveType getEllipticCurveType() {
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.(KnownOpenSSLEllipticCurveAlgorithmConstant)
.getNormalizedName(), _, result)
}
override int getKeySize() {
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.(KnownOpenSSLEllipticCurveAlgorithmConstant)
.getNormalizedName(), result, _)
}
}

View File

@@ -1,8 +1,9 @@
import cpp
import experimental.quantum.Language
import KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import AlgToAVCFlow
private import experimental.quantum.Language
private import KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
private import AlgToAVCFlow
predicate knownOpenSSLConstantToHashFamilyType(
KnownOpenSSLHashAlgorithmConstant e, Crypto::THashType type

View File

@@ -1,5 +1,5 @@
import cpp
import experimental.quantum.OpenSSL.LibraryDetector
private import experimental.quantum.OpenSSL.LibraryDetector
predicate resolveAlgorithmFromExpr(Expr e, string normalizedName, string algType) {
resolveAlgorithmFromCall(e, normalizedName, algType)
@@ -67,6 +67,15 @@ class KnownOpenSSLHashAlgorithmConstant extends KnownOpenSSLAlgorithmConstant {
}
}
class KnownOpenSSLEllipticCurveAlgorithmConstant extends KnownOpenSSLAlgorithmConstant {
KnownOpenSSLEllipticCurveAlgorithmConstant() {
exists(string algType |
resolveAlgorithmFromExpr(this, _, algType) and
algType.toLowerCase().matches("elliptic_curve")
)
}
}
/**
* Resolves a call to a 'direct algorithm getter', e.g., EVP_MD5()
* This approach to fetching algorithms was used in OpenSSL 1.0.2.

View File

@@ -1,5 +1,5 @@
import experimental.quantum.Language
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
abstract class OpenSSLAlgorithmInstance extends Crypto::AlgorithmInstance {
abstract OpenSSLAlgorithmValueConsumer getAVC();

View File

@@ -3,3 +3,4 @@ import CipherAlgorithmInstance
import PaddingAlgorithmInstance
import BlockAlgorithmInstance
import HashAlgorithmInstance
import EllipticCurveAlgorithmInstance

View File

@@ -1,9 +1,10 @@
import cpp
import experimental.quantum.Language
import OpenSSLAlgorithmInstanceBase
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import AlgToAVCFlow
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
private import experimental.quantum.Language
private import OpenSSLAlgorithmInstanceBase
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import AlgToAVCFlow
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
/**
* Given a `KnownOpenSSLPaddingAlgorithmConstant`, converts this to a padding family type.

View File

@@ -1,9 +1,9 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.LibraryDetector
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
import OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.LibraryDetector
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
private import OpenSSLAlgorithmValueConsumerBase
abstract class CipherAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }

View File

@@ -1,7 +1,7 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
// TODO: can self referential to itself, which is also an algorithm (Known algorithm)
/**

View File

@@ -0,0 +1,36 @@
import cpp
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.LibraryDetector
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
abstract class EllipticCurveValueConsumer extends OpenSSLAlgorithmValueConsumer { }
//https://docs.openssl.org/3.0/man3/EC_KEY_new/#name
class EVPEllipticCurveAlgorithmConsumer extends EllipticCurveValueConsumer {
DataFlow::Node valueArgNode;
DataFlow::Node resultNode;
EVPEllipticCurveAlgorithmConsumer() {
resultNode.asExpr() = this.(Call) and // in all cases the result is the return
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
(
this.(Call).getTarget().getName() in ["EVP_EC_gen", "EC_KEY_new_by_curve_name"] and
valueArgNode.asExpr() = this.(Call).getArgument(0)
or
this.(Call).getTarget().getName() in [
"EC_KEY_new_by_curve_name_ex", "EVP_PKEY_CTX_set_ec_paramgen_curve_nid"
] and
valueArgNode.asExpr() = this.(Call).getArgument(2)
)
}
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
}
override DataFlow::Node getResultNode() { result = resultNode }
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
}

View File

@@ -1,12 +1,9 @@
// import EVPHashInitializer
// import EVPHashOperation
// import EVPHashAlgorithmSource
import cpp
import experimental.quantum.Language
import semmle.code.cpp.dataflow.new.DataFlow
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
import experimental.quantum.OpenSSL.LibraryDetector
private import experimental.quantum.Language
private import semmle.code.cpp.dataflow.new.DataFlow
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
private import experimental.quantum.OpenSSL.LibraryDetector
abstract class HashAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }

View File

@@ -1,5 +1,5 @@
import experimental.quantum.Language
import semmle.code.cpp.dataflow.new.DataFlow
private import experimental.quantum.Language
private import semmle.code.cpp.dataflow.new.DataFlow
abstract class OpenSSLAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Call {
/**

View File

@@ -3,3 +3,4 @@ import CipherAlgorithmValueConsumer
import DirectAlgorithmValueConsumer
import PaddingAlgorithmValueConsumer
import HashAlgorithmValueConsumer
import EllipticCurveAlgorithmValueConsumer

View File

@@ -1,9 +1,9 @@
import cpp
import experimental.quantum.Language
import experimental.quantum.OpenSSL.LibraryDetector
import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
import OpenSSLAlgorithmValueConsumerBase
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.LibraryDetector
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
private import OpenSSLAlgorithmValueConsumerBase
abstract class PaddingAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }

View File

@@ -6,4 +6,5 @@ module OpenSSLModel {
import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
import experimental.quantum.OpenSSL.Random
}

View File

@@ -3,8 +3,8 @@
* Models cipher initialization for EVP cipher operations.
*/
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] }

View File

@@ -1,8 +1,8 @@
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
import EVPCipherInitializer
import OpenSSLOperationBase
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
private import EVPCipherInitializer
private import OpenSSLOperationBase
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
@@ -74,8 +74,8 @@ class EVP_Cipher_Call extends EVP_Cipher_Operation {
}
// NOTE: not modeled as cipher operations, these are intermediate calls
class EVP_Update_Call extends Call {
EVP_Update_Call() {
class EVP_Cipher_Update_Call extends Call {
EVP_Cipher_Update_Call() {
this.(Call).getTarget().getName() in [
"EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate"
]
@@ -88,15 +88,15 @@ class EVP_Update_Call extends Call {
Expr getContextArg() { result = this.(Call).getArgument(0) }
}
class EVP_Final_Call extends EVP_Cipher_Operation {
EVP_Final_Call() {
class EVP_Cipher_Final_Call extends EVP_Cipher_Operation {
EVP_Cipher_Final_Call() {
this.(Call).getTarget().getName() in [
"EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal",
"EVP_DecryptFinal", "EVP_CipherFinal"
]
}
EVP_Update_Call getUpdateCalls() {
EVP_Cipher_Update_Call getUpdateCalls() {
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
}

View File

@@ -2,12 +2,12 @@
* https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
*/
import experimental.quantum.Language
import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
import experimental.quantum.OpenSSL.LibraryDetector
import OpenSSLOperationBase
import EVPHashInitializer
import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
private import experimental.quantum.OpenSSL.LibraryDetector
private import OpenSSLOperationBase
private import EVPHashInitializer
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
// import EVPHashConsumers
abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance {
@@ -16,6 +16,16 @@ abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperatio
EVP_Hash_Initializer getInitCall() {
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
}
/**
* By default, the algorithm value comes from the init call.
* There are variants where this isn't true, in which case the
* subclass should override this method.
*/
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
}
}
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
@@ -88,30 +98,34 @@ class EVP_Digest_Operation extends EVP_Hash_Operation {
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
}
// // override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
// // AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
// // DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
// // }
// // ***** TODO *** complete modelinlg for hash operations, but have consideration for terminal and non-terminal (non intermedaite) steps
// // see the JCA. May need to update the cipher operations similarly
// // ALSO SEE cipher for how we currently model initialization of the algorithm through an init call
// class EVP_DigestUpdate_Operation extends EVP_Hash_Operation {
// EVP_DigestUpdate_Operation() {
// this.(Call).getTarget().getName() = "EVP_DigestUpdate" and
// isPossibleOpenSSLFunction(this.(Call).getTarget())
// }
// override Crypto::AlgorithmConsumer getAlgorithmConsumer() {
// this.getInitCall().getAlgorithmArg() = result
// }
// }
// class EVP_DigestFinal_Variants_Operation extends EVP_Hash_Operation {
// EVP_DigestFinal_Variants_Operation() {
// this.(Call).getTarget().getName() in [
// "EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"
// ] and
// isPossibleOpenSSLFunction(this.(Call).getTarget())
// }
// override Crypto::AlgorithmConsumer getAlgorithmConsumer() {
// this.getInitCall().getAlgorithmArg() = result
// }
// }
// NOTE: not modeled as hash operations, these are intermediate calls
class EVP_Digest_Update_Call extends Call {
EVP_Digest_Update_Call() { this.(Call).getTarget().getName() in ["EVP_DigestUpdate"] }
Expr getInputArg() { result = this.(Call).getArgument(1) }
DataFlow::Node getInputNode() { result.asExpr() = this.getInputArg() }
Expr getContextArg() { result = this.(Call).getArgument(0) }
}
class EVP_Digest_Final_Call extends EVP_Hash_Operation {
EVP_Digest_Final_Call() {
this.(Call).getTarget().getName() in [
"EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"
]
}
EVP_Digest_Update_Call getUpdateCalls() {
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
}
override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() }
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() }
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() }
}

View File

@@ -1,4 +1,4 @@
import experimental.quantum.Language
private import experimental.quantum.Language
abstract class OpenSSLOperation extends Crypto::OperationInstance instanceof Call {
abstract Expr getInputArg();

View File

@@ -98,19 +98,6 @@ class Node extends TNode {
/** Gets the location of this element. */
Location getLocation() { none() } // overridden by subclasses
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/**
* Gets an upper bound on the type of this node.
*/

View File

@@ -538,19 +538,6 @@ class Node extends TIRDataFlowNode {
none() // overridden by subclasses
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
deprecated predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this element. */
cached
final string toString() {

View File

@@ -45,6 +45,28 @@ private module Cached {
)
}
private Expr getRankedElementExpr(ArrayAggregateLiteral aggr, int rnk) {
result =
rank[rnk + 1](Expr e, int elementIndex, int position |
e = aggr.getElementExpr(elementIndex, position)
|
e order by elementIndex, position
)
}
private class LastArrayAggregateStore extends StoreInstruction {
ArrayAggregateLiteral aggr;
LastArrayAggregateStore() {
exists(int rnk |
this.getSourceValue().getUnconvertedResultExpression() = getRankedElementExpr(aggr, rnk) and
not exists(getRankedElementExpr(aggr, rnk + 1))
)
}
ArrayAggregateLiteral getArrayAggregateLiteral() { result = aggr }
}
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
// IR construction inserts an additional cast to a `size_t` on the extent
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
@@ -95,6 +117,16 @@ private module Cached {
tco.producesExprResult() and
result = asDefinitionImpl0(instr)
)
or
// IR construction breaks an array aggregate literal `{1, 2, 3}` into a
// sequence of `StoreInstruction`s. So there's no instruction `i` for which
// `i.getUnconvertedResultExpression() instanceof ArrayAggregateLiteral`.
// So we map the instruction node corresponding to the last `Store`
// instruction of the sequence to the result of the array aggregate
// literal. This makes sense since this store will immediately flow into
// the indirect node representing the array. So this node does represent
// the array after it has been fully initialized.
result = instr.(LastArrayAggregateStore).getArrayAggregateLiteral()
}
private Expr getConvertedResultExpressionImpl(Instruction instr) {

View File

@@ -10,7 +10,7 @@ private import SemanticExprSpecific::SemanticExprConfig as Specific
*/
class SemBasicBlock extends Specific::BasicBlock {
/** Holds if this block (transitively) dominates `otherblock`. */
final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
final predicate dominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
/** Gets an expression that is evaluated in this basic block. */
final SemExpr getAnExpr() { result.getBasicBlock() = this }

View File

@@ -42,58 +42,6 @@ class SecurityOptions extends string {
)
}
/**
* The argument of the given function is filled in from user input.
*/
deprecated predicate userInputArgument(FunctionCall functionCall, int arg) {
exists(string fname |
functionCall.getTarget().hasGlobalOrStdName(fname) and
exists(functionCall.getArgument(arg)) and
(
fname = ["fread", "fgets", "fgetws", "gets"] and arg = 0
or
fname = "scanf" and arg >= 1
or
fname = "fscanf" and arg >= 2
)
or
functionCall.getTarget().hasGlobalName(fname) and
exists(functionCall.getArgument(arg)) and
fname = "getaddrinfo" and
arg = 3
)
or
exists(RemoteFlowSourceFunction remote, FunctionOutput output |
functionCall.getTarget() = remote and
output.isParameterDerefOrQualifierObject(arg) and
remote.hasRemoteFlowSource(output, _)
)
}
/**
* The return value of the given function is filled in from user input.
*/
deprecated predicate userInputReturned(FunctionCall functionCall) {
exists(string fname |
functionCall.getTarget().getName() = fname and
(
fname = ["fgets", "gets"] or
this.userInputReturn(fname)
)
)
or
exists(RemoteFlowSourceFunction remote, FunctionOutput output |
functionCall.getTarget() = remote and
(output.isReturnValue() or output.isReturnValueDeref()) and
remote.hasRemoteFlowSource(output, _)
)
}
/**
* DEPRECATED: Users should override `userInputReturned()` instead.
*/
deprecated predicate userInputReturn(string function) { none() }
/**
* The argument of the given function is used for running a process or loading
* a library.
@@ -108,29 +56,6 @@ class SecurityOptions extends string {
function = ["LoadLibrary", "LoadLibraryA", "LoadLibraryW"] and arg = 0
}
/**
* This predicate should hold if the expression is directly
* computed from user input. Such expressions are treated as
* sources of taint.
*/
deprecated predicate isUserInput(Expr expr, string cause) {
exists(FunctionCall fc, int i |
this.userInputArgument(fc, i) and
expr = fc.getArgument(i) and
cause = fc.getTarget().getName()
)
or
exists(FunctionCall fc |
this.userInputReturned(fc) and
expr = fc and
cause = fc.getTarget().getName()
)
or
commandLineArg(expr) and cause = "argv"
or
expr.(EnvironmentRead).getSourceDescription() = cause
}
/**
* This predicate should hold if the expression raises privilege for the
* current session. The default definition only holds true for some
@@ -152,16 +77,6 @@ class SecurityOptions extends string {
}
}
/**
* An access to the argv argument to main().
*/
private predicate commandLineArg(Expr e) {
exists(Parameter argv |
argv(argv) and
argv.getAnAccess() = e
)
}
/** The argv parameter to the main function */
predicate argv(Parameter argv) {
exists(Function f |
@@ -173,21 +88,6 @@ predicate argv(Parameter argv) {
/** Convenience accessor for SecurityOptions.isPureFunction */
predicate isPureFunction(string name) { exists(SecurityOptions opts | opts.isPureFunction(name)) }
/** Convenience accessor for SecurityOptions.userInputArgument */
deprecated predicate userInputArgument(FunctionCall functionCall, int arg) {
exists(SecurityOptions opts | opts.userInputArgument(functionCall, arg))
}
/** Convenience accessor for SecurityOptions.userInputReturn */
deprecated predicate userInputReturned(FunctionCall functionCall) {
exists(SecurityOptions opts | opts.userInputReturned(functionCall))
}
/** Convenience accessor for SecurityOptions.isUserInput */
deprecated predicate isUserInput(Expr expr, string cause) {
exists(SecurityOptions opts | opts.isUserInput(expr, cause))
}
/** Convenience accessor for SecurityOptions.isProcessOperationArgument */
predicate isProcessOperationArgument(string function, int arg) {
exists(SecurityOptions opts | opts.isProcessOperationArgument(function, arg))

View File

@@ -22,28 +22,4 @@ class CustomSecurityOptions extends SecurityOptions {
// for example: (function = "MySpecialSqlFunction" and arg = 0)
none() // rules to match custom functions replace this line
}
deprecated override predicate userInputArgument(FunctionCall functionCall, int arg) {
SecurityOptions.super.userInputArgument(functionCall, arg)
or
exists(string fname |
functionCall.getTarget().hasGlobalName(fname) and
exists(functionCall.getArgument(arg)) and
// --- custom functions that return user input via one of their arguments:
// 'arg' is the 0-based index of the argument that is used to return user input
// for example: (fname = "readXmlInto" and arg = 1)
none() // rules to match custom functions replace this line
)
}
deprecated override predicate userInputReturned(FunctionCall functionCall) {
SecurityOptions.super.userInputReturned(functionCall)
or
exists(string fname |
functionCall.getTarget().hasGlobalName(fname) and
// --- custom functions that return user input via their return value:
// for example: fname = "xmlReadAttribute"
none() // rules to match custom functions replace this line
)
}
}

View File

@@ -26,7 +26,7 @@ module IRFlowTest<IRDataFlow::GlobalFlowSig Flow> implements TestSig {
n =
strictcount(int line, int column |
Flow::flow(any(IRDataFlow::Node otherSource |
otherSource.hasLocationInfo(_, line, column, _, _)
otherSource.getLocation().hasLocationInfo(_, line, column, _, _)
), sink)
) and
(
@@ -55,7 +55,7 @@ module AstFlowTest<AstDataFlow::GlobalFlowSig Flow> implements TestSig {
n =
strictcount(int line, int column |
Flow::flow(any(AstDataFlow::Node otherSource |
otherSource.hasLocationInfo(_, line, column, _, _)
otherSource.getLocation().hasLocationInfo(_, line, column, _, _)
), sink)
) and
(

View File

@@ -35,6 +35,6 @@ void test_aggregate_literal() {
S s5 = {.a = 1, .b = 2}; // $ asExpr=1 asExpr=2 asExpr={...}
int xs[] = {1, 2, 3}; // $ asExpr=1 asExpr=2 asExpr=3 MISSING: asExpr={...}
const int ys[] = {[0] = 4, [1] = 5, [0] = 6}; // $ asExpr=4 asExpr=5 asExpr=6 MISSING: asExpr={...}
int xs[] = {1, 2, 3}; // $ asExpr=1 asExpr=2 asExpr=3 asExpr={...}
const int ys[] = {[0] = 4, [1] = 5, [0] = 6}; // $ asExpr=4 asExpr=5 asExpr=6 asExpr={...}
}

View File

@@ -2,8 +2,8 @@ edges
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:25:2:25:4 | *a | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:30:9:30:14 | *access to array | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:123:2:123:12 | *... = ... | provenance | |
| consts.cpp:25:2:25:4 | *a | consts.cpp:26:2:26:4 | *b | provenance | |
| consts.cpp:26:2:26:4 | *b | consts.cpp:24:7:24:9 | **gv1 | provenance | |
| consts.cpp:25:2:25:4 | *a | consts.cpp:26:2:26:4 | *{...} | provenance | |
| consts.cpp:26:2:26:4 | *{...} | consts.cpp:24:7:24:9 | **gv1 | provenance | |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | provenance | |
| consts.cpp:30:9:30:14 | *access to array | consts.cpp:29:7:29:25 | **nonConstFuncToArray | provenance | |
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:86:9:86:10 | *v1 | provenance | |
@@ -14,7 +14,7 @@ edges
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:129:19:129:20 | *v1 | provenance | |
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:135:9:135:11 | *v10 | provenance | TaintFunction |
| consts.cpp:90:2:90:14 | *... = ... | consts.cpp:91:9:91:10 | *v2 | provenance | |
| consts.cpp:90:2:90:14 | *... = ... | consts.cpp:115:21:115:22 | *v2 | provenance | |
| consts.cpp:90:2:90:14 | *... = ... | consts.cpp:115:21:115:22 | *{...} | provenance | |
| consts.cpp:90:7:90:10 | *call to gets | consts.cpp:90:2:90:14 | *... = ... | provenance | |
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:94:13:94:14 | *v1 | provenance | |
| consts.cpp:90:12:90:13 | gets output argument | consts.cpp:99:2:99:8 | *... = ... | provenance | |
@@ -28,9 +28,9 @@ edges
| consts.cpp:106:13:106:19 | *call to varFunc | consts.cpp:107:9:107:10 | *v5 | provenance | |
| consts.cpp:111:2:111:15 | *... = ... | consts.cpp:112:9:112:10 | *v6 | provenance | |
| consts.cpp:111:7:111:13 | *call to varFunc | consts.cpp:111:2:111:15 | *... = ... | provenance | |
| consts.cpp:115:17:115:18 | *v1 | consts.cpp:115:21:115:22 | *v2 | provenance | |
| consts.cpp:115:21:115:22 | *v2 | consts.cpp:116:9:116:13 | *access to array | provenance | |
| consts.cpp:115:21:115:22 | *v2 | consts.cpp:120:2:120:11 | *... = ... | provenance | |
| consts.cpp:115:17:115:18 | *v1 | consts.cpp:115:21:115:22 | *{...} | provenance | |
| consts.cpp:115:21:115:22 | *{...} | consts.cpp:116:9:116:13 | *access to array | provenance | |
| consts.cpp:115:21:115:22 | *{...} | consts.cpp:120:2:120:11 | *... = ... | provenance | |
| consts.cpp:120:2:120:11 | *... = ... | consts.cpp:121:9:121:10 | *v8 | provenance | |
| consts.cpp:123:2:123:12 | *... = ... | consts.cpp:24:7:24:9 | **gv1 | provenance | |
| consts.cpp:129:19:129:20 | *v1 | consts.cpp:130:9:130:10 | *v9 | provenance | |
@@ -39,7 +39,7 @@ edges
nodes
| consts.cpp:24:7:24:9 | **gv1 | semmle.label | **gv1 |
| consts.cpp:25:2:25:4 | *a | semmle.label | *a |
| consts.cpp:26:2:26:4 | *b | semmle.label | *b |
| consts.cpp:26:2:26:4 | *{...} | semmle.label | *{...} |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | semmle.label | **nonConstFuncToArray |
| consts.cpp:30:9:30:14 | *access to array | semmle.label | *access to array |
| consts.cpp:85:7:85:8 | gets output argument | semmle.label | gets output argument |
@@ -60,7 +60,7 @@ nodes
| consts.cpp:111:7:111:13 | *call to varFunc | semmle.label | *call to varFunc |
| consts.cpp:112:9:112:10 | *v6 | semmle.label | *v6 |
| consts.cpp:115:17:115:18 | *v1 | semmle.label | *v1 |
| consts.cpp:115:21:115:22 | *v2 | semmle.label | *v2 |
| consts.cpp:115:21:115:22 | *{...} | semmle.label | *{...} |
| consts.cpp:116:9:116:13 | *access to array | semmle.label | *access to array |
| consts.cpp:120:2:120:11 | *... = ... | semmle.label | *... = ... |
| consts.cpp:121:9:121:10 | *v8 | semmle.label | *v8 |

View File

@@ -6,8 +6,8 @@ edges
| test.cpp:28:10:28:29 | *http://example.com | test.cpp:11:26:11:28 | *url | provenance | |
| test.cpp:35:23:35:42 | *http://example.com | test.cpp:35:23:35:42 | *http://example.com | provenance | |
| test.cpp:35:23:35:42 | *http://example.com | test.cpp:39:11:39:15 | *url_l | provenance | |
| test.cpp:36:26:36:45 | *http://example.com | test.cpp:36:26:36:45 | *http://example.com | provenance | |
| test.cpp:36:26:36:45 | *http://example.com | test.cpp:40:11:40:17 | *access to array | provenance | |
| test.cpp:36:26:36:45 | *http://example.com | test.cpp:36:26:36:45 | *{...} | provenance | |
| test.cpp:36:26:36:45 | *{...} | test.cpp:40:11:40:17 | *access to array | provenance | |
| test.cpp:38:11:38:15 | *url_g | test.cpp:11:26:11:28 | *url | provenance | |
| test.cpp:39:11:39:15 | *url_l | test.cpp:11:26:11:28 | *url | provenance | |
| test.cpp:40:11:40:17 | *access to array | test.cpp:11:26:11:28 | *url | provenance | |
@@ -29,7 +29,7 @@ nodes
| test.cpp:35:23:35:42 | *http://example.com | semmle.label | *http://example.com |
| test.cpp:35:23:35:42 | *http://example.com | semmle.label | *http://example.com |
| test.cpp:36:26:36:45 | *http://example.com | semmle.label | *http://example.com |
| test.cpp:36:26:36:45 | *http://example.com | semmle.label | *http://example.com |
| test.cpp:36:26:36:45 | *{...} | semmle.label | *{...} |
| test.cpp:38:11:38:15 | *url_g | semmle.label | *url_g |
| test.cpp:39:11:39:15 | *url_l | semmle.label | *url_l |
| test.cpp:40:11:40:17 | *access to array | semmle.label | *access to array |

View File

@@ -1,5 +1,5 @@
{
"sdk": {
"version": "9.0.100"
"version": "9.0.300"
}
}

View File

@@ -3,8 +3,8 @@
| BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | $@ flows to here and is written to HTML or JavaScript. | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | User-provided value |
| BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | $@ flows to here and is written to HTML or JavaScript. | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | User-provided value |
edges
| BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:569:16:577:13 | call to method TypeCheck<String> : String | provenance | Src:MaD:2 MaD:3 |
| test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:569:16:577:13 | call to method TypeCheck<String> : String | BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | provenance | Sink:MaD:1 |
| BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:553:16:561:13 | call to method TypeCheck<String> : String | provenance | Src:MaD:2 MaD:3 |
| test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:553:16:561:13 | call to method TypeCheck<String> : String | BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | provenance | Sink:MaD:1 |
models
| 1 | Sink: Microsoft.AspNetCore.Components; MarkupString; false; MarkupString; (System.String); ; Argument[0]; html-injection; manual |
| 2 | Source: Microsoft.AspNetCore.Components; SupplyParameterFromQueryAttribute; false; ; ; Attribute.Getter; ReturnValue; remote; manual |
@@ -14,5 +14,5 @@ nodes
| BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | semmle.label | access to property UrlParam |
| BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | semmle.label | access to property QueryParam |
| BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | semmle.label | access to property QueryParam : String |
| test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:569:16:577:13 | call to method TypeCheck<String> : String | semmle.label | call to method TypeCheck<String> : String |
| test-db/working/razor/AC613014E59A413B9538FF8068364499/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:553:16:561:13 | call to method TypeCheck<String> : String | semmle.label | call to method TypeCheck<String> : String |
subpaths

View File

@@ -38,7 +38,6 @@ ql/csharp/ql/src/Concurrency/SynchSetUnsynchGet.ql
ql/csharp/ql/src/Concurrency/UnsafeLazyInitialization.ql
ql/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.ql
ql/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql
ql/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql
ql/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql
ql/csharp/ql/src/Diagnostics/CompilerError.ql
ql/csharp/ql/src/Diagnostics/CompilerMessage.ql
@@ -146,8 +145,6 @@ ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql
ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-730/ReDoS.ql
ql/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql
ql/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql
ql/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql
ql/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql

View File

@@ -1,5 +1,4 @@
ql/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql
ql/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql
ql/csharp/ql/src/Diagnostics/CompilerError.ql
ql/csharp/ql/src/Diagnostics/CompilerMessage.ql
ql/csharp/ql/src/Diagnostics/DiagnosticExtractionErrors.ql
@@ -49,8 +48,6 @@ ql/csharp/ql/src/Security Features/CWE-639/InsecureDirectObjectReference.ql
ql/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql
ql/csharp/ql/src/Security Features/CWE-730/ReDoS.ql
ql/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql
ql/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql
ql/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql
ql/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql

View File

@@ -26,6 +26,7 @@ ql/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql
ql/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql
ql/csharp/ql/src/Bad Practices/UseOfHtmlInputHidden.ql
ql/csharp/ql/src/Bad Practices/UseOfSystemOutputStream.ql
ql/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql
ql/csharp/ql/src/Dead Code/DeadRefTypes.ql
ql/csharp/ql/src/Dead Code/NonAssignedFields.ql
ql/csharp/ql/src/Dead Code/UnusedField.ql
@@ -89,6 +90,8 @@ ql/csharp/ql/src/Security Features/CWE-321/HardcodedSymmetricEncryptionKey.ql
ql/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql
ql/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql
ql/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql
ql/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql
ql/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql
ql/csharp/ql/src/Useless code/PointlessForwardingMethod.ql
ql/csharp/ql/src/definitions.ql

View File

@@ -4,7 +4,7 @@
* @kind problem
* @problem.severity warning
* @security-severity 7.5
* @precision medium
* @precision low
* @id cs/password-in-configuration
* @tags security
* external/cwe/cwe-013

View File

@@ -4,7 +4,7 @@
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision medium
* @precision low
* @id cs/hardcoded-connection-string-credentials
* @tags security
* external/cwe/cwe-259

View File

@@ -4,7 +4,7 @@
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision medium
* @precision low
* @id cs/hardcoded-credentials
* @tags security
* external/cwe/cwe-259

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The queries `cs/password-in-configuration`, `cs/hardcoded-credentials` and `cs/hardcoded-connection-string-credentials` have been removed from all query suites.

View File

@@ -35,7 +35,7 @@ Bug Fixes
GitHub Actions
""""""""""""""
* The :code:`actions/unversioned-immutable-action` query will no longer report any alerts, since the Immutable Actions feature is not yet available for customer use. The query remains in the default Code Scanning suites for use internal to GitHub. Once the Immutable Actions feature is available, the query will be updated to report alerts again.
* The :code:`actions/unversioned-immutable-action` query will no longer report any alerts, since the Immutable Actions feature is not yet available for customer use. The query has also been moved to the experimental folder and will not be used in code scanning unless it is explicitly added to a code scanning configuration. Once the Immutable Actions feature is available, the query will be updated to report alerts again.
Major Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -37,14 +37,6 @@ Bug Fixes
Query Packs
-----------
New Features
~~~~~~~~~~~~
GitHub Actions
""""""""""""""
* CodeQL and Copilot Autofix support for GitHub Actions is now Generally Available.
Bug Fixes
~~~~~~~~~
@@ -87,6 +79,14 @@ Python
* The :code:`py/mixed-tuple-returns` query no longer flags instances where the tuple is passed into the function as an argument, as this led to too many false positives.
New Features
~~~~~~~~~~~~
GitHub Actions
""""""""""""""
* CodeQL and Copilot Autofix support for GitHub Actions is now Generally Available.
Language Libraries
------------------
@@ -131,17 +131,17 @@ Ruby
New Features
~~~~~~~~~~~~
GitHub Actions
""""""""""""""
* CodeQL and Copilot Autofix support for GitHub Actions is now Generally Available.
C/C++
"""""
* Calling conventions explicitly specified on function declarations (:code:`__cdecl`, :code:`__stdcall`, :code:`__fastcall`, etc.) are now represented as specifiers of those declarations.
* A new class :code:`CallingConventionSpecifier` extending the :code:`Specifier` class was introduced, which represents explicitly specified calling conventions.
GitHub Actions
""""""""""""""
* CodeQL and Copilot Autofix support for GitHub Actions is now Generally Available.
Shared Libraries
----------------

View File

@@ -0,0 +1,159 @@
.. _codeql-cli-2.21.3:
==========================
CodeQL 2.21.3 (2025-05-15)
==========================
.. 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.21.3 runs a total of 452 security queries when configured with the Default suite (covering 168 CWE). The Extended suite enables an additional 136 queries (covering 35 more CWE).
CodeQL CLI
----------
Miscellaneous
~~~~~~~~~~~~~
* Windows binaries for the CodeQL CLI are now built with :code:`/guard:cf`, enabling `Control Flow Guard <https://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard>`__.
Query Packs
-----------
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
C#
""
* Changed the precision of the :code:`cs/equality-on-floats` query from medium to high.
JavaScript/TypeScript
"""""""""""""""""""""
* Type information is now propagated more precisely through :code:`Promise.all()` calls,
leading to more resolved calls and more sources and sinks being detected.
Query Metadata Changes
~~~~~~~~~~~~~~~~~~~~~~
C/C++
"""""
* The tag :code:`external/cwe/cwe-14` has been removed from :code:`cpp/memset-may-be-deleted` and the tag :code:`external/cwe/cwe-014` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cpp/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cpp/count-untrusted-data-external-api-ir` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cpp/untrusted-data-to-external-api-ir` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cpp/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cpp/late-check-of-function-argument` and the tag :code:`external/cwe/cwe-020` has been added.
C#
""
* The tag :code:`external/cwe/cwe-13` has been removed from :code:`cs/password-in-configuration` and the tag :code:`external/cwe/cwe-013` has been added.
* The tag :code:`external/cwe/cwe-11` has been removed from :code:`cs/web/debug-binary` and the tag :code:`external/cwe/cwe-011` has been added.
* The tag :code:`external/cwe/cwe-16` has been removed from :code:`cs/web/large-max-request-length` and the tag :code:`external/cwe/cwe-016` has been added.
* The tag :code:`external/cwe/cwe-16` has been removed from :code:`cs/web/request-validation-disabled` and the tag :code:`external/cwe/cwe-016` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cs/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cs/serialization-check-bypass` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`cs/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-12` has been removed from :code:`cs/web/missing-global-error-handler` and the tag :code:`external/cwe/cwe-012` has been added.
Golang
""""""
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/incomplete-hostname-regexp` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/regex/missing-regexp-anchor` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/suspicious-character-in-regex` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`go/untrusted-data-to-unknown-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-90` has been removed from :code:`go/ldap-injection` and the tag :code:`external/cwe/cwe-090` has been added.
* The tag :code:`external/cwe/cwe-74` has been removed from :code:`go/dsn-injection` and the tag :code:`external/cwe/cwe-074` has been added.
* The tag :code:`external/cwe/cwe-74` has been removed from :code:`go/dsn-injection-local` and the tag :code:`external/cwe/cwe-074` has been added.
* The tag :code:`external/cwe/cwe-79` has been removed from :code:`go/html-template-escaping-passthrough` and the tag :code:`external/cwe/cwe-079` has been added.
Java/Kotlin
"""""""""""
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`java/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`java/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-93` has been removed from :code:`java/netty-http-request-or-response-splitting` and the tag :code:`external/cwe/cwe-093` has been added.
JavaScript/TypeScript
"""""""""""""""""""""
* The tag :code:`external/cwe/cwe-79` has been removed from :code:`js/disabling-electron-websecurity` and the tag :code:`external/cwe/cwe-079` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`js/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`js/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`js/untrusted-data-to-external-api-more-sources` and the tag :code:`external/cwe/cwe-020` has been added.
Python
""""""
* The tags :code:`security/cwe/cwe-94` and :code:`security/cwe/cwe-95` have been removed from :code:`py/use-of-input` and the tags :code:`external/cwe/cwe-094` and :code:`external/cwe/cwe-095` have been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`py/count-untrusted-data-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`py/untrusted-data-to-external-api` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`py/cookie-injection` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-20` has been removed from :code:`py/incomplete-url-substring-sanitization` and the tag :code:`external/cwe/cwe-020` has been added.
* The tag :code:`external/cwe/cwe-94` has been removed from :code:`py/js2py-rce` and the tag :code:`external/cwe/cwe-094` has been added.
Ruby
""""
* The precision of :code:`rb/useless-assignment-to-local` has been adjusted from :code:`medium` to :code:`high`.
* The tag :code:`external/cwe/cwe-94` has been removed from :code:`rb/server-side-template-injection` and the tag :code:`external/cwe/cwe-094` has been added.
Language Libraries
------------------
Bug Fixes
~~~~~~~~~
C/C++
"""""
* Fixed an infinite loop in :code:`semmle.code.cpp.rangeanalysis.new.RangeAnalysis` when computing ranges in very large and complex function bodies.
Minor Analysis Improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
JavaScript/TypeScript
"""""""""""""""""""""
* Enhanced modeling of the `fastify <https://www.npmjs.com/package/fastify>`__ framework to support the :code:`all` route handler method.
* Improved modeling of the |link-code-shelljs-1|_ and |link-code-async-shelljs-2|_ libraries by adding support for the :code:`which`, :code:`cmd`, :code:`asyncExec` and :code:`env`.
* Added support for the :code:`fastify` :code:`addHook` method.
Python
""""""
* Added modeling for the :code:`hdbcli` PyPI package as a database library implementing PEP 249.
* Added header write model for :code:`send_header` in :code:`http.server`.
New Features
~~~~~~~~~~~~
Java/Kotlin
"""""""""""
* Kotlin versions up to 2.2.0\ *x* are now supported. Support for the Kotlin 1.5.x series is dropped (so the minimum Kotlin version is now 1.6.0).
Swift
"""""
* Added AST nodes :code:`UnsafeCastExpr`, :code:`TypeValueExpr`, :code:`IntegerType`, and :code:`BuiltinFixedArrayType` that correspond to new nodes added by Swift 6.1.
.. |link-code-shelljs-1| replace:: :code:`shelljs`\
.. _link-code-shelljs-1: https://www.npmjs.com/package/shelljs
.. |link-code-async-shelljs-2| replace:: :code:`async-shelljs`\
.. _link-code-async-shelljs-2: https://www.npmjs.com/package/async-shelljs

View File

@@ -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.21.3
codeql-cli-2.21.2
codeql-cli-2.21.1
codeql-cli-2.21.0

View File

@@ -25,7 +25,7 @@
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_"
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
Swift [11]_,"Swift 5.4-6.0","Swift compiler","``.swift``"
Swift [11]_,"Swift 5.4-6.1","Swift compiler","``.swift``"
TypeScript [12]_,"2.6-5.8",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group

View File

@@ -50,6 +50,5 @@ ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql
ql/go/ql/src/Security/CWE-770/UncontrolledAllocationSize.ql
ql/go/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/go/ql/src/Security/CWE-918/RequestForgery.ql
ql/go/ql/src/Summary/LinesOfCode.ql

View File

@@ -28,6 +28,5 @@ ql/go/ql/src/Security/CWE-640/EmailInjection.ql
ql/go/ql/src/Security/CWE-643/XPathInjection.ql
ql/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql
ql/go/ql/src/Security/CWE-770/UncontrolledAllocationSize.ql
ql/go/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/go/ql/src/Security/CWE-918/RequestForgery.ql
ql/go/ql/src/Summary/LinesOfCode.ql

View File

@@ -6,6 +6,7 @@ ql/go/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql
ql/go/ql/src/Security/CWE-020/UntrustedDataToUnknownExternalAPI.ql
ql/go/ql/src/Security/CWE-078/StoredCommand.ql
ql/go/ql/src/Security/CWE-079/StoredXss.ql
ql/go/ql/src/Security/CWE-798/HardcodedCredentials.ql
ql/go/ql/src/definitions.ql
ql/go/ql/src/experimental/CWE-090/LDAPInjection.ql
ql/go/ql/src/experimental/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -30,10 +30,6 @@ No user-facing changes.
* The member predicate `hasLocationInfo` has been deprecated on the following classes: `BasicBlock`, `Callable`, `Content`, `ContentSet`, `ControlFlow::Node`, `DataFlowCallable`, `DataFlow::Node`, `Entity`, `GVN`, `HtmlTemplate::TemplateStmt`, `IR:WriteTarget`, `SourceSinkInterpretationInput::SourceOrSinkElement`, `SourceSinkInterpretationInput::InterpretNode`, `SsaVariable`, `SsaDefinition`, `SsaWithFields`, `StringOps::ConcatenationElement`, `Type`, and `VariableWithFields`. Use `getLocation()` instead.
### Major Analysis Improvements
* Go 1.24 is now supported. This includes the new language feature of generic type aliases.
### Minor Analysis Improvements
* The location info for the following classes has been changed slightly to match a location that is in the database: `BasicBlock`, `ControlFlow::EntryNode`, `ControlFlow::ExitNode`, `ControlFlow::ConditionGuardNode`, `IR::ImplicitLiteralElementIndexInstruction`, `IR::EvalImplicitTrueInstruction`, `SsaImplicitDefinition`, `SsaPhiNode`.
@@ -48,6 +44,10 @@ No user-facing changes.
* The member predicate `getNamedType` on `GoMicro::ServiceInterfaceType` has been deprecated. Use the new member predicate `getDefinedType` instead.
* The member predicate `getNamedType` on `Twirp::ServiceInterfaceType` has been deprecated. Use the new member predicate `getDefinedType` instead.
### Major Analysis Improvements
* Go 1.24 is now supported. This includes the new language feature of generic type aliases.
### Minor Analysis Improvements
* Taint models have been added for the `weak` package, which was added in Go 1.24.

View File

@@ -6,6 +6,10 @@
* The member predicate `getNamedType` on `GoMicro::ServiceInterfaceType` has been deprecated. Use the new member predicate `getDefinedType` instead.
* The member predicate `getNamedType` on `Twirp::ServiceInterfaceType` has been deprecated. Use the new member predicate `getDefinedType` instead.
### Major Analysis Improvements
* Go 1.24 is now supported. This includes the new language feature of generic type aliases.
### Minor Analysis Improvements
* Taint models have been added for the `weak` package, which was added in Go 1.24.

View File

@@ -4,10 +4,6 @@
* The member predicate `hasLocationInfo` has been deprecated on the following classes: `BasicBlock`, `Callable`, `Content`, `ContentSet`, `ControlFlow::Node`, `DataFlowCallable`, `DataFlow::Node`, `Entity`, `GVN`, `HtmlTemplate::TemplateStmt`, `IR:WriteTarget`, `SourceSinkInterpretationInput::SourceOrSinkElement`, `SourceSinkInterpretationInput::InterpretNode`, `SsaVariable`, `SsaDefinition`, `SsaWithFields`, `StringOps::ConcatenationElement`, `Type`, and `VariableWithFields`. Use `getLocation()` instead.
### Major Analysis Improvements
* Go 1.24 is now supported. This includes the new language feature of generic type aliases.
### Minor Analysis Improvements
* The location info for the following classes has been changed slightly to match a location that is in the database: `BasicBlock`, `ControlFlow::EntryNode`, `ControlFlow::ExitNode`, `ControlFlow::ConditionGuardNode`, `IR::ImplicitLiteralElementIndexInstruction`, `IR::EvalImplicitTrueInstruction`, `SsaImplicitDefinition`, `SsaPhiNode`.

View File

@@ -5,7 +5,7 @@
* @kind problem
* @problem.severity warning
* @security-severity 9.8
* @precision medium
* @precision low
* @id go/hardcoded-credentials
* @tags security
* external/cwe/cwe-259

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `go/hardcoded-credentials` has been removed from all query suites.

View File

@@ -196,7 +196,6 @@ ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
ql/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql
ql/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql
ql/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
ql/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql
ql/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql
ql/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql

View File

@@ -99,7 +99,6 @@ ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
ql/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql
ql/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql
ql/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
ql/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql
ql/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql
ql/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql

View File

@@ -158,6 +158,7 @@ ql/java/ql/src/Security/CWE/CWE-312/CleartextStorageClass.ql
ql/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql
ql/java/ql/src/Security/CWE/CWE-319/UseSSL.ql
ql/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsComparison.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsSourceCall.ql
ql/java/ql/src/Security/CWE/CWE-798/HardcodedPasswordField.ql

View File

@@ -20,7 +20,7 @@ No user-facing changes.
### Minor Analysis Improvements
* Java extraction is now able to download Maven 3.9.x if a Maven Enforcer Plugin configuration indicates it is necessary. Maven 3.8.x is still preferred if the enforcer-plugin configuration (if any) permits it.
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure '/', '\', '..' are not in the path.
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure `/`, `\\`, `..` are not in the path.
### Bug Fixes
@@ -55,8 +55,8 @@ No user-facing changes.
* Deleted the deprecated `isLValue` and `isRValue` predicates from the `VarAccess` class, use `isVarWrite` and `isVarRead` respectively instead.
* Deleted the deprecated `getRhs` predicate from the `VarWrite` class, use `getASource` instead.
* Deleted the deprecated `LValue` and `RValue` classes, use `VarWrite` and `VarRead` respectively instead.
* Deleted a lot of deprecated classes ending in "*Access", use the corresponding "*Call" classes instead.
* Deleted a lot of deprecated predicates ending in "*Access", use the corresponding "*Call" predicates instead.
* Deleted a lot of deprecated classes ending in `*Access`, use the corresponding `*Call` classes instead.
* Deleted a lot of deprecated predicates ending in `*Access`, use the corresponding `*Call` predicates instead.
* Deleted the deprecated `EnvInput` and `DatabaseInput` classes from `FlowSources.qll`, use the threat models feature instead.
* Deleted some deprecated API predicates from `SensitiveApi.qll`, use the Sink classes from that file instead.

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* Java now uses the shared `BasicBlock` library. This means that the names of several member predicates have been changed to align with the names used in other languages. The old predicates have been deprecated. The `BasicBlock` class itself no longer extends `ControlFlowNode` - the predicate `getFirstNode` can be used to fix any QL code that somehow relied on this.

View File

@@ -5,8 +5,8 @@
* Deleted the deprecated `isLValue` and `isRValue` predicates from the `VarAccess` class, use `isVarWrite` and `isVarRead` respectively instead.
* Deleted the deprecated `getRhs` predicate from the `VarWrite` class, use `getASource` instead.
* Deleted the deprecated `LValue` and `RValue` classes, use `VarWrite` and `VarRead` respectively instead.
* Deleted a lot of deprecated classes ending in "*Access", use the corresponding "*Call" classes instead.
* Deleted a lot of deprecated predicates ending in "*Access", use the corresponding "*Call" predicates instead.
* Deleted a lot of deprecated classes ending in `*Access`, use the corresponding `*Call` classes instead.
* Deleted a lot of deprecated predicates ending in `*Access`, use the corresponding `*Call` predicates instead.
* Deleted the deprecated `EnvInput` and `DatabaseInput` classes from `FlowSources.qll`, use the threat models feature instead.
* Deleted some deprecated API predicates from `SensitiveApi.qll`, use the Sink classes from that file instead.

View File

@@ -3,7 +3,7 @@
### Minor Analysis Improvements
* Java extraction is now able to download Maven 3.9.x if a Maven Enforcer Plugin configuration indicates it is necessary. Maven 3.8.x is still preferred if the enforcer-plugin configuration (if any) permits it.
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure '/', '\', '..' are not in the path.
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure `/`, `\\`, `..` are not in the path.
### Bug Fixes

View File

@@ -1606,13 +1606,8 @@ module JCAModel {
else result = Crypto::OtherEllipticCurveType()
}
override string getKeySize() {
exists(int keySize |
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), keySize,
_)
|
result = keySize.toString()
)
override int getKeySize() {
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), result, _)
}
EllipticCurveAlgorithmValueConsumer getConsumer() { result = consumer }

View File

@@ -6,6 +6,7 @@ extractor: java
library: true
upgrades: upgrades
dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/mad: ${workspace}
codeql/quantum: ${workspace}

View File

@@ -4,91 +4,128 @@
import java
import Dominance
private import codeql.controlflow.BasicBlock as BB
cached
private module BasicBlockStage {
cached
predicate ref() { any() }
private module Input implements BB::InputSig<Location> {
import SuccessorType
cached
predicate backref() {
(exists(any(BasicBlock bb).getABBSuccessor()) implies any()) and
(exists(any(BasicBlock bb).getNode(_)) implies any()) and
(exists(any(BasicBlock bb).length()) implies any())
/** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) { none() }
/** A delineated part of the AST with its own CFG. */
class CfgScope = Callable;
/** The class of control flow nodes. */
class Node = ControlFlowNode;
/** Gets the CFG scope in which this node occurs. */
CfgScope nodeGetCfgScope(Node node) { node.getEnclosingCallable() = result }
private Node getASpecificSuccessor(Node node, SuccessorType t) {
node.(ConditionNode).getABranchSuccessor(t.(BooleanSuccessor).getValue()) = result
or
node.getAnExceptionSuccessor() = result and t instanceof ExceptionSuccessor
}
/** Gets an immediate successor of this node. */
Node nodeGetASuccessor(Node node, SuccessorType t) {
result = getASpecificSuccessor(node, t)
or
node.getASuccessor() = result and
t instanceof NormalSuccessor and
not result = getASpecificSuccessor(node, _)
}
/**
* Holds if `node` represents an entry node to be used when calculating
* dominance.
*/
predicate nodeIsDominanceEntry(Node node) {
exists(Stmt entrystmt | entrystmt = node.asStmt() |
exists(Callable c | entrystmt = c.getBody())
or
// This disjunct is technically superfluous, but safeguards against extractor problems.
entrystmt instanceof BlockStmt and
not exists(entrystmt.getEnclosingCallable()) and
not entrystmt.getParent() instanceof Stmt
)
}
/**
* Holds if `node` represents an exit node to be used when calculating
* post dominance.
*/
predicate nodeIsPostDominanceExit(Node node) { node instanceof ControlFlow::ExitNode }
}
private module BbImpl = BB::Make<Location, Input>;
import BbImpl
/** Holds if the dominance relation is calculated for `bb`. */
predicate hasDominanceInformation(BasicBlock bb) {
exists(BasicBlock entry |
Input::nodeIsDominanceEntry(entry.getFirstNode()) and entry.getASuccessor*() = bb
)
}
/**
* A control-flow node that represents the start of a basic block.
*
* A basic block is a series of nodes with no control-flow branching, which can
* often be treated as a unit in analyses.
* A basic block, that is, a maximal straight-line sequence of control flow nodes
* without branches or joins.
*/
class BasicBlock extends ControlFlowNode {
cached
BasicBlock() {
BasicBlockStage::ref() and
not exists(this.getAPredecessor()) and
exists(this.getASuccessor())
or
strictcount(this.getAPredecessor()) > 1
or
exists(ControlFlowNode pred | pred = this.getAPredecessor() |
strictcount(pred.getASuccessor()) > 1
)
}
class BasicBlock extends BbImpl::BasicBlock {
/** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() { result = this.getScope() }
/** Gets an immediate successor of this basic block. */
cached
BasicBlock getABBSuccessor() {
BasicBlockStage::ref() and
result = this.getLastNode().getASuccessor()
}
/**
* Holds if this basic block dominates basic block `bb`.
*
* That is, all paths reaching `bb` from the entry point basic block must
* go through this basic block.
*/
predicate dominates(BasicBlock bb) { super.dominates(bb) }
/** Gets an immediate predecessor of this basic block. */
BasicBlock getABBPredecessor() { result.getABBSuccessor() = this }
/**
* DEPRECATED: Use `getASuccessor` instead.
*
* Gets an immediate successor of this basic block.
*/
deprecated BasicBlock getABBSuccessor() { result = this.getASuccessor() }
/** Gets a control-flow node contained in this basic block. */
ControlFlowNode getANode() { result = this.getNode(_) }
/**
* DEPRECATED: Use `getAPredecessor` instead.
*
* Gets an immediate predecessor of this basic block.
*/
deprecated BasicBlock getABBPredecessor() { result.getASuccessor() = this }
/** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */
cached
ControlFlowNode getNode(int pos) {
BasicBlockStage::ref() and
result = this and
pos = 0
or
exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 |
this.getNode(mid_pos) = mid and
mid.getASuccessor() = result and
not result instanceof BasicBlock
)
}
/**
* DEPRECATED: Use `strictlyDominates` instead.
*
* Holds if this basic block strictly dominates `node`.
*/
deprecated predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) }
/** Gets the first control-flow node in this basic block. */
ControlFlowNode getFirstNode() { result = this }
/**
* DEPRECATED: Use `dominates` instead.
*
* Holds if this basic block dominates `node`. (This is reflexive.)
*/
deprecated predicate bbDominates(BasicBlock node) { this.dominates(node) }
/** Gets the last control-flow node in this basic block. */
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
/**
* DEPRECATED: Use `strictlyPostDominates` instead.
*
* Holds if this basic block strictly post-dominates `node`.
*/
deprecated predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) }
/** Gets the number of control-flow nodes contained in this basic block. */
cached
int length() {
BasicBlockStage::ref() and
result = strictcount(this.getANode())
}
/** Holds if this basic block strictly dominates `node`. */
predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) }
/** Holds if this basic block dominates `node`. (This is reflexive.) */
predicate bbDominates(BasicBlock node) { bbDominates(this, node) }
/** Holds if this basic block strictly post-dominates `node`. */
predicate bbStrictlyPostDominates(BasicBlock node) { bbStrictlyPostDominates(this, node) }
/** Holds if this basic block post-dominates `node`. (This is reflexive.) */
predicate bbPostDominates(BasicBlock node) { bbPostDominates(this, node) }
/**
* DEPRECATED: Use `postDominates` instead.
*
* Holds if this basic block post-dominates `node`. (This is reflexive.)
*/
deprecated predicate bbPostDominates(BasicBlock node) { this.postDominates(node) }
}
/** A basic block that ends in an exit node. */

View File

@@ -8,91 +8,75 @@ import java
* Predicates for basic-block-level dominance.
*/
/** Entry points for control-flow. */
private predicate flowEntry(BasicBlock entry) {
exists(Stmt entrystmt | entrystmt = entry.getFirstNode().asStmt() |
exists(Callable c | entrystmt = c.getBody())
or
// This disjunct is technically superfluous, but safeguards against extractor problems.
entrystmt instanceof BlockStmt and
not exists(entry.getEnclosingCallable()) and
not entrystmt.getParent() instanceof Stmt
)
}
/** The successor relation for basic blocks. */
private predicate bbSucc(BasicBlock pre, BasicBlock post) { post = pre.getABBSuccessor() }
/** The immediate dominance relation for basic blocks. */
cached
predicate bbIDominates(BasicBlock dom, BasicBlock node) =
idominance(flowEntry/1, bbSucc/2)(_, dom, node)
/** Holds if the dominance relation is calculated for `bb`. */
predicate hasDominanceInformation(BasicBlock bb) {
exists(BasicBlock entry | flowEntry(entry) and bbSucc*(entry, bb))
/**
* DEPRECATED: Use `BasicBlock::immediatelyDominates` instead.
*
* The immediate dominance relation for basic blocks.
*/
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock node) {
dom.immediatelyDominates(node)
}
/** Exit points for basic-block control-flow. */
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
/** Reversed `bbSucc`. */
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() }
/** The immediate post-dominance relation on basic blocks. */
cached
predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
idominance(bbSink/1, bbPred/2)(_, dominator, node)
/** Holds if `dom` strictly dominates `node`. */
predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) { bbIDominates+(dom, node) }
/** Holds if `dom` dominates `node`. (This is reflexive.) */
predicate bbDominates(BasicBlock dom, BasicBlock node) {
bbStrictlyDominates(dom, node) or dom = node
/**
* DEPRECATED: Use `BasicBlock::strictlyDominates` instead.
*
* Holds if `dom` strictly dominates `node`.
*/
deprecated predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) {
dom.strictlyDominates(node)
}
/** Holds if `dom` strictly post-dominates `node`. */
predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) { bbIPostDominates+(dom, node) }
/**
* DEPRECATED: Use `BasicBlock::dominates` instead.
*
* Holds if `dom` dominates `node`. (This is reflexive.)
*/
deprecated predicate bbDominates(BasicBlock dom, BasicBlock node) { dom.dominates(node) }
/** Holds if `dom` post-dominates `node`. (This is reflexive.) */
predicate bbPostDominates(BasicBlock dom, BasicBlock node) {
bbStrictlyPostDominates(dom, node) or dom = node
/**
* DEPRECATED: Use `BasicBlock::strictlyPostDominates` instead.
*
* Holds if `dom` strictly post-dominates `node`.
*/
deprecated predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) {
dom.strictlyPostDominates(node)
}
/**
* DEPRECATED: Use `BasicBlock::postDominates` instead.
*
* Holds if `dom` post-dominates `node`. (This is reflexive.)
*/
deprecated predicate bbPostDominates(BasicBlock dom, BasicBlock node) { dom.postDominates(node) }
/**
* The dominance frontier relation for basic blocks.
*
* This is equivalent to:
*
* ```
* bbDominates(x, w.getABBPredecessor()) and not bbStrictlyDominates(x, w)
* x.dominates(w.getAPredecessor()) and not x.strictlyDominates(w)
* ```
*/
predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
x = w.getABBPredecessor() and not bbIDominates(x, w)
x = w.getAPredecessor() and not x.immediatelyDominates(w)
or
exists(BasicBlock prev | dominanceFrontier(prev, w) |
bbIDominates(x, prev) and
not bbIDominates(x, w)
x.immediatelyDominates(prev) and
not x.immediatelyDominates(w)
)
}
/**
* Holds if `(bb1, bb2)` is an edge that dominates `bb2`, that is, all other
* predecessors of `bb2` are dominated by `bb2`. This implies that `bb1` is the
* immediate dominator of `bb2`.
*
* This is a necessary and sufficient condition for an edge to dominate anything,
* and in particular `dominatingEdge(bb1, bb2) and bb2.bbDominates(bb3)` means
* that the edge `(bb1, bb2)` dominates `bb3`.
*/
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
bbIDominates(bb1, bb2) and
bb1.getABBSuccessor() = bb2 and
forall(BasicBlock pred | pred = bb2.getABBPredecessor() and pred != bb1 | bbDominates(bb2, pred))
}
/*
* Predicates for expression-level dominance.
*/
@@ -102,7 +86,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
exists(BasicBlock bb, int i | dominator = bb.getNode(i) and node = bb.getNode(i + 1))
or
exists(BasicBlock dom, BasicBlock bb |
bbIDominates(dom, bb) and
dom.immediatelyDominates(bb) and
dominator = dom.getLastNode() and
node = bb.getFirstNode()
)
@@ -112,7 +96,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
pragma[inline]
predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined.
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i < j)
}
@@ -121,7 +105,7 @@ predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline]
predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined.
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i <= j)
}
@@ -130,7 +114,7 @@ predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline]
predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined.
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i > j)
}
@@ -139,7 +123,7 @@ predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
pragma[inline]
predicate postDominates(ControlFlowNode dom, ControlFlowNode node) {
// This predicate is gigantic, so it must be inlined.
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
or
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i >= j)
}

View File

@@ -23,7 +23,7 @@ class ConditionBlock extends BasicBlock {
/** Gets a `true`- or `false`-successor of the last node of this basic block. */
BasicBlock getTestSuccessor(boolean testIsTrue) {
result = this.getConditionNode().getABranchSuccessor(testIsTrue)
result.getFirstNode() = this.getConditionNode().getABranchSuccessor(testIsTrue)
}
/*
@@ -68,7 +68,7 @@ class ConditionBlock extends BasicBlock {
exists(BasicBlock succ |
succ = this.getTestSuccessor(testIsTrue) and
dominatingEdge(this, succ) and
succ.bbDominates(controlled)
succ.dominates(controlled)
)
}
}
@@ -287,7 +287,7 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
// Pattern cases are handled as condition blocks
not sc instanceof PatternCase and
caseblock.getFirstNode() = sc.getControlFlowNode() and
caseblock.bbDominates(bb) and
caseblock.dominates(bb) and
// Check we can't fall through from a previous block:
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
isNonFallThroughPredecessor(sc, pred)
@@ -300,14 +300,14 @@ private predicate preconditionBranchEdge(
) {
conditionCheckArgument(ma, _, branch) and
bb1.getLastNode() = ma.getControlFlowNode() and
bb2 = bb1.getLastNode().getANormalSuccessor()
bb2.getFirstNode() = bb1.getLastNode().getANormalSuccessor()
}
private predicate preconditionControls(MethodCall ma, BasicBlock controlled, boolean branch) {
exists(BasicBlock check, BasicBlock succ |
preconditionBranchEdge(ma, check, succ, branch) and
dominatingEdge(check, succ) and
succ.bbDominates(controlled)
succ.dominates(controlled)
)
}

View File

@@ -47,7 +47,7 @@ private predicate callAlwaysPerformsAction(Call call, ActionConfiguration conf)
private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) {
exists(ExitBlock exit |
exit.getEnclosingCallable() = callable and
actionBlock(conf).bbDominates(exit)
actionBlock(conf).dominates(exit)
)
}
@@ -56,12 +56,12 @@ private BasicBlock nonDominatingActionBlock(ActionConfiguration conf) {
exists(ExitBlock exit |
result = actionBlock(conf) and
exit.getEnclosingCallable() = result.getEnclosingCallable() and
not result.bbDominates(exit)
not result.dominates(exit)
)
}
private class JoinBlock extends BasicBlock {
JoinBlock() { 2 <= strictcount(this.getABBPredecessor()) }
JoinBlock() { 2 <= strictcount(this.getAPredecessor()) }
}
/**
@@ -72,8 +72,8 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
bb = nonDominatingActionBlock(conf)
or
if bb instanceof JoinBlock
then forall(BasicBlock pred | pred = bb.getABBPredecessor() | postActionBlock(pred, conf))
else postActionBlock(bb.getABBPredecessor(), conf)
then forall(BasicBlock pred | pred = bb.getAPredecessor() | postActionBlock(pred, conf))
else postActionBlock(bb.getAPredecessor(), conf)
}
/** Holds if every path through `callable` goes through at least one action node. */

View File

@@ -0,0 +1,72 @@
/**
* Provides different types of control flow successor types.
*/
import java
private import codeql.util.Boolean
private newtype TSuccessorType =
TNormalSuccessor() or
TBooleanSuccessor(Boolean branch) or
TExceptionSuccessor()
/** The type of a control flow successor. */
class SuccessorType extends TSuccessorType {
/** Gets a textual representation of successor type. */
string toString() { result = "SuccessorType" }
}
/** A normal control flow successor. */
class NormalSuccessor extends SuccessorType, TNormalSuccessor { }
/**
* An exceptional control flow successor.
*
* This marks control flow edges that are taken when an exception is thrown.
*/
class ExceptionSuccessor extends SuccessorType, TExceptionSuccessor { }
/**
* A conditional control flow successor.
*
* This currently only includes boolean successors (`BooleanSuccessor`).
*/
class ConditionalSuccessor extends SuccessorType, TBooleanSuccessor {
/** Gets the Boolean value of this successor. */
boolean getValue() { this = TBooleanSuccessor(result) }
}
/**
* A Boolean control flow successor.
*
* For example, this program fragment:
*
* ```java
* if (x < 0)
* return 0;
* else
* return 1;
* ```
*
* has a control flow graph containing Boolean successors:
*
* ```
* if
* |
* x < 0
* / \
* / \
* / \
* true false
* | \
* return 0 return 1
* ```
*/
class BooleanSuccessor = ConditionalSuccessor;
/**
* A nullness control flow successor. This is currently unused for Java.
*/
class NullnessSuccessor extends ConditionalSuccessor {
NullnessSuccessor() { none() }
}

View File

@@ -209,7 +209,7 @@ class UnreachableBasicBlock extends BasicBlock {
or
// This block is not reachable in the CFG, and is not the entrypoint in a callable, an
// expression in an assert statement, or a catch clause.
forall(BasicBlock bb | bb = this.getABBPredecessor() | bb instanceof UnreachableBasicBlock) and
forall(BasicBlock bb | bb = this.getAPredecessor() | bb instanceof UnreachableBasicBlock) and
not exists(Callable c | c.getBody().getControlFlowNode() = this.getFirstNode()) and
not this.getFirstNode().asExpr().getEnclosingStmt() instanceof AssertStmt and
not this.getFirstNode().asStmt() instanceof CatchClause
@@ -219,11 +219,10 @@ class UnreachableBasicBlock extends BasicBlock {
// Not accessible from the switch expression
unreachableCaseBlock = constSwitchStmt.getAFailingCase().getBasicBlock() and
// Not accessible from the successful case
not constSwitchStmt.getMatchingCase().getBasicBlock().getABBSuccessor*() =
unreachableCaseBlock
not constSwitchStmt.getMatchingCase().getBasicBlock().getASuccessor*() = unreachableCaseBlock
|
// Blocks dominated by an unreachable case block are unreachable
unreachableCaseBlock.bbDominates(this)
unreachableCaseBlock.dominates(this)
)
}
}

View File

@@ -239,7 +239,7 @@ SsaVariable getADefinition(SsaVariable v, boolean fromBackEdge) {
exists(SsaVariable inp, BasicBlock bb, boolean fbe |
v.(SsaPhiNode).hasInputFromBlock(inp, bb) and
result = getADefinition(inp, fbe) and
(if v.getBasicBlock().bbDominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
(if v.getBasicBlock().dominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
)
}
@@ -290,10 +290,10 @@ private predicate guardImpliesEqual(Guard guard, boolean branch, SsaVariable v,
)
}
private ControlFlowNode getAGuardBranchSuccessor(Guard g, boolean branch) {
result = g.(Expr).getControlFlowNode().(ConditionNode).getABranchSuccessor(branch)
private BasicBlock getAGuardBranchSuccessor(Guard g, boolean branch) {
result.getFirstNode() = g.(Expr).getControlFlowNode().(ConditionNode).getABranchSuccessor(branch)
or
result = g.(SwitchCase).getControlFlowNode() and branch = true
result.getFirstNode() = g.(SwitchCase).getControlFlowNode() and branch = true
}
/**
@@ -306,7 +306,7 @@ private predicate guardControlsPhiBranch(
guard.directlyControls(upd.getBasicBlock(), branch) and
upd.getDefiningExpr().(VariableAssign).getSource() = e and
upd = phi.getAPhiInput() and
guard.getBasicBlock().bbStrictlyDominates(phi.getBasicBlock())
guard.getBasicBlock().strictlyDominates(phi.getBasicBlock())
}
/**
@@ -331,7 +331,7 @@ private predicate conditionalAssign(SsaVariable v, Guard guard, boolean branch,
forall(SsaVariable other | other != upd and other = phi.getAPhiInput() |
guard.directlyControls(other.getBasicBlock(), branch.booleanNot())
or
other.getBasicBlock().bbDominates(guard.getBasicBlock()) and
other.getBasicBlock().dominates(guard.getBasicBlock()) and
not other.isLiveAtEndOfBlock(getAGuardBranchSuccessor(guard, branch))
)
)

View File

@@ -298,9 +298,9 @@ private predicate impossibleEdge(BasicBlock bb1, BasicBlock bb2) {
private predicate leavingFinally(BasicBlock bb1, BasicBlock bb2, boolean normaledge) {
exists(TryStmt try, BlockStmt finally |
try.getFinally() = finally and
bb1.getABBSuccessor() = bb2 and
bb1.getEnclosingStmt().getEnclosingStmt*() = finally and
not bb2.getEnclosingStmt().getEnclosingStmt*() = finally and
bb1.getASuccessor() = bb2 and
bb1.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
not bb2.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
if bb1.getLastNode().getANormalSuccessor() = bb2.getFirstNode()
then normaledge = true
else normaledge = false
@@ -339,7 +339,7 @@ private predicate nullVarStep(
midssa.isLiveAtEndOfBlock(mid) and
not ensureNotNull(midssa).getBasicBlock() = mid and
not assertFail(mid, _) and
bb = mid.getABBSuccessor() and
bb = mid.getASuccessor() and
not impossibleEdge(mid, bb) and
not exists(boolean branch | nullGuard(midssa, branch, false).hasBranchEdge(mid, bb, branch)) and
not (leavingFinally(mid, bb, true) and midstoredcompletion = true) and

View File

@@ -209,13 +209,13 @@ module Sem implements Semantic<Location> {
class BasicBlock = J::BasicBlock;
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
private predicate id(ExprParent x, ExprParent y) { x = y }
private predicate idOfAst(ExprParent x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getAstNode(), y) }
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getFirstNode().getAstNode(), y) }
int getBlockId1(BasicBlock bb) { idOf(bb, result) }

View File

@@ -321,14 +321,14 @@ private module Input implements TypeFlowInput<Location> {
*/
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) {
ioe.getExpr() = v.getAUse() and
strictcount(bb.getABBPredecessor()) > 1 and
strictcount(bb.getAPredecessor()) > 1 and
exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb)
}
/** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */
private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) {
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
strictcount(bb.getABBPredecessor())
strictcount(bb.getAPredecessor())
}
/**
@@ -338,7 +338,7 @@ private module Input implements TypeFlowInput<Location> {
predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) {
exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va |
instanceofDisjunction(bb, v) and
bb.bbDominates(va.getBasicBlock()) and
bb.dominates(va.getBasicBlock()) and
va = v.getAUse() and
instanceofDisjunct(ioe, bb, v) and
t = ioe.getSyntacticCheckedType() and

View File

@@ -145,7 +145,7 @@ private module BaseSsaImpl {
/** Holds if `v` has an implicit definition at the entry, `b`, of the callable. */
predicate hasEntryDef(BaseSsaSourceVariable v, BasicBlock b) {
exists(LocalScopeVariable l, Callable c |
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
v = TLocalVar(c, l) and c.getBody().getBasicBlock() = b
|
l instanceof Parameter or
l.getCallable() != c
@@ -157,15 +157,14 @@ private import BaseSsaImpl
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J
private import semmle.code.java.controlflow.Dominance as Dom
class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) }
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class SourceVariable = BaseSsaSourceVariable;

View File

@@ -83,12 +83,12 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { bbIDominates(result, bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) {
result = bb.(J::BasicBlock).getABBSuccessor()
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result.(J::BasicBlock).immediatelyDominates(bb)
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(J::BasicBlock).getASuccessor() }
//TODO: support capture of `this` in lambdas
class CapturedVariable instanceof LocalScopeVariable {
CapturedVariable() {

View File

@@ -40,14 +40,14 @@ private module ThisFlow {
private int lastRank(BasicBlock b) { result = max(int rankix | thisRank(_, b, rankix)) }
private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getABBSuccessor*(), _) }
private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getASuccessor*(), _) }
private predicate thisAccessBlockReaches(BasicBlock b1, BasicBlock b2) {
thisAccess(_, b1, _) and b2 = b1.getABBSuccessor()
thisAccess(_, b1, _) and b2 = b1.getASuccessor()
or
exists(BasicBlock mid |
thisAccessBlockReaches(b1, mid) and
b2 = mid.getABBSuccessor() and
b2 = mid.getASuccessor() and
not thisAccess(_, mid, _) and
blockPrecedesThisAccess(b2)
)

View File

@@ -144,13 +144,13 @@ private predicate certainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBl
pragma[nomagic]
private predicate hasEntryDef(TrackedVar v, BasicBlock b) {
exists(LocalScopeVariable l, Callable c |
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
v = TLocalVar(c, l) and c.getBody().getBasicBlock() = b
|
l instanceof Parameter or
l.getCallable() != c
)
or
v instanceof SsaSourceField and v.getEnclosingCallable().getBody().getControlFlowNode() = b
v instanceof SsaSourceField and v.getEnclosingCallable().getBody().getBasicBlock() = b
}
/** Holds if `n` might update the locally tracked variable `v`. */
@@ -165,15 +165,14 @@ private predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, Basic
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J
private import semmle.code.java.controlflow.Dominance as Dom
class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) }
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class SourceVariable = SsaSourceVariable;

View File

@@ -19,7 +19,7 @@ private predicate id(BB::ExprParent x, BB::ExprParent y) { x = y }
private predicate idOfAst(BB::ExprParent x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getAstNode(), y) }
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getFirstNode().getAstNode(), y) }
private int getId(BasicBlock bb) { idOf(bb, result) }

View File

@@ -24,6 +24,6 @@ private class SslProceedCall extends MethodCall {
/** Holds if `m` trusts all certificates by calling `SslErrorHandler.proceed` unconditionally. */
predicate trustsAllCerts(OnReceivedSslErrorMethod m) {
exists(SslProceedCall pr | pr.getQualifier().(VarAccess).getVariable() = m.handlerArg() |
pr.getBasicBlock().bbPostDominates(m.getBody().getBasicBlock())
pr.getBasicBlock().postDominates(m.getBody().getBasicBlock())
)
}

View File

@@ -21,7 +21,7 @@ private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
validationMethod(ma.getMethod(), pos) and
ma.getArgument(pos) = rv and
adjacentUseUseSameVar(rv, result.asExpr()) and
ma.getBasicBlock().bbDominates(result.asExpr().getBasicBlock())
ma.getBasicBlock().dominates(result.asExpr().getBasicBlock())
)
}

View File

@@ -168,7 +168,7 @@ private class FullyDecodesUrlBarrier extends DataFlow::Node {
exists(Variable v, Expr e | this.asExpr() = v.getAnAccess() |
fullyDecodesUrlGuard(e) and
e = v.getAnAccess() and
e.getBasicBlock().bbDominates(this.asExpr().getBasicBlock())
e.getBasicBlock().dominates(this.asExpr().getBasicBlock())
)
}
}

View File

@@ -40,16 +40,16 @@ private predicate validatedAccess(VarAccess va) {
guardcall.getControlFlowNode() = node
|
exists(BasicBlock succ |
succ = node.getANormalSuccessor() and
succ.getFirstNode() = node.getANormalSuccessor() and
dominatingEdge(node.getBasicBlock(), succ) and
succ.bbDominates(va.getBasicBlock())
succ.dominates(va.getBasicBlock())
)
or
exists(BasicBlock bb, int i |
bb.getNode(i) = node and
bb.getNode(i + 1) = node.getANormalSuccessor()
|
bb.bbStrictlyDominates(va.getBasicBlock()) or
bb.strictlyDominates(va.getBasicBlock()) or
bb.getNode(any(int j | j > i)).asExpr() = va
)
)

View File

@@ -99,8 +99,8 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
)
) and
(
lock.getAnExceptionSuccessor() = exblock or
lock.(ConditionNode).getAFalseSuccessor() = exblock
lock.getAnExceptionSuccessor() = exblock.getFirstNode() or
lock.(ConditionNode).getAFalseSuccessor() = exblock.getFirstNode()
)
)
}
@@ -113,7 +113,7 @@ predicate heldByCurrentThreadCheck(LockType t, BasicBlock checkblock, BasicBlock
exists(ConditionBlock conditionBlock |
conditionBlock.getCondition() = t.getIsHeldByCurrentThreadAccess()
|
conditionBlock.getBasicBlock() = checkblock and
conditionBlock = checkblock and
conditionBlock.getTestSuccessor(false) = falsesucc
)
}
@@ -133,7 +133,7 @@ predicate variableLockStateCheck(LockType t, BasicBlock checkblock, BasicBlock f
conditionBlock.getTestSuccessor(true) = t.getUnlockAccess().getBasicBlock() and
conditionBlock.getCondition() = v
|
conditionBlock.getBasicBlock() = checkblock and
conditionBlock = checkblock and
conditionBlock.getTestSuccessor(false) = falsesucc
)
}
@@ -145,9 +145,7 @@ predicate variableLockStateCheck(LockType t, BasicBlock checkblock, BasicBlock f
predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) {
lockUnlockBlock(t, b, locks) and src = b and locks > 0
or
exists(BasicBlock pred, int predlocks, int curlocks, int failedlock |
pred = b.getABBPredecessor()
|
exists(BasicBlock pred, int predlocks, int curlocks, int failedlock | pred = b.getAPredecessor() |
// The number of net locks from the `src` block to the predecessor block `pred` is `predlocks`.
blockIsLocked(t, src, pred, predlocks) and
// The recursive call ensures that at least one lock is held, so do not consider the false

View File

@@ -18,6 +18,6 @@ where
iteration = inner.getAnIterationVariable() and
iteration = outer.getAnIterationVariable() and
inner.getEnclosingStmt+() = outer and
inner.getBasicBlock().getABBSuccessor+() = outer.getCondition().getBasicBlock()
inner.getBasicBlock().getASuccessor+() = outer.getCondition().getBasicBlock()
select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.",
iteration, iteration.getName(), outer, "for statement"

View File

@@ -4,7 +4,7 @@
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision medium
* @precision low
* @id java/hardcoded-credential-api-call
* @tags security
* external/cwe/cwe-798

View File

@@ -37,7 +37,7 @@ predicate overwritten(VariableUpdate upd) {
bb1.getNode(i) = upd.getControlFlowNode() and
bb2.getNode(j) = overwrite.getControlFlowNode()
|
bb1.getABBSuccessor+() = bb2
bb1.getASuccessor+() = bb2
or
bb1 = bb2 and i < j
)

View File

@@ -14,7 +14,7 @@ private predicate blockInSwitch(SwitchStmt s, BasicBlock b) {
private predicate switchCaseControlFlow(SwitchStmt switch, BasicBlock b1, BasicBlock b2) {
blockInSwitch(switch, b1) and
b1.getABBSuccessor() = b2 and
b1.getASuccessor() = b2 and
blockInSwitch(switch, b2)
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `java/hardcoded-credential-api-call` has been removed from all query suites.

View File

@@ -13,7 +13,7 @@ import semmle.code.java.dataflow.SSA
class SsaConvertibleReadAccess extends VarRead {
SsaConvertibleReadAccess() {
this.getEnclosingCallable().getBody().getBasicBlock().getABBSuccessor*() = this.getBasicBlock() and
this.getEnclosingCallable().getBody().getBasicBlock().getASuccessor*() = this.getBasicBlock() and
(
not exists(this.getQualifier())
or

View File

@@ -1,6 +1,6 @@
import default
import java
import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2)
where b.strictlyDominates(b2)
select b, b2

View File

@@ -1,5 +1,5 @@
import default
import java
from BasicBlock b, BasicBlock b2
where b.getABBSuccessor() = b2
where b.getASuccessor() = b2
select b, b2

View File

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node
where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
strictlyDominates(dom, node) and
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node

View File

@@ -1,6 +1,6 @@
import default
import java
import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2)
where b.strictlyDominates(b2)
select b, b2

View File

@@ -1,5 +1,5 @@
import default
import java
from BasicBlock b, BasicBlock b2
where b.getABBSuccessor() = b2
where b.getASuccessor() = b2
select b, b2

View File

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node
where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
strictlyDominates(dom, node) and
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node

View File

@@ -1,6 +1,6 @@
import default
import java
import semmle.code.java.controlflow.Dominance
from BasicBlock b, BasicBlock b2
where bbStrictlyDominates(b, b2)
where b.strictlyDominates(b2)
select b, b2

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