+
+After fetching an SSL certificate, always check the result of certificate verification.
+
+
+
+
+Always check the result of SSL certificate verification. A certificate that has been revoked may indicate that data is coming from an attacker, whereas a certificate that has expired or was self-signed may indicate an increased likelihood that the data is malicious.
+
+
+
+
+In this example, the SSL_get_peer_certificate function is used to get the certificate of a peer. However it is unsafe to use that information without checking if the certificate is valid.
+
+
+
+In the corrected example, we use SSL_get_verify_result to check that certificate verification was successful.
+
+
+
+
+
+
+
+
diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql
new file mode 100644
index 00000000000..ad66bd2bd57
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql
@@ -0,0 +1,120 @@
+/**
+ * @name Certificate not checked
+ * @description Always check the result of certificate verification after fetching an SSL certificate.
+ * @kind problem
+ * @problem.severity error
+ * @security-severity 7.5
+ * @precision medium
+ * @id cpp/certificate-not-checked
+ * @tags security
+ * external/cwe/cwe-295
+ */
+
+import cpp
+import semmle.code.cpp.valuenumbering.GlobalValueNumbering
+import semmle.code.cpp.controlflow.IRGuards
+
+/**
+ * A call to `SSL_get_peer_certificate`.
+ */
+class SSLGetPeerCertificateCall extends FunctionCall {
+ SSLGetPeerCertificateCall() {
+ getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
+ }
+
+ Expr getSSLArgument() { result = getArgument(0) }
+}
+
+/**
+ * A call to `SSL_get_verify_result`.
+ */
+class SSLGetVerifyResultCall extends FunctionCall {
+ SSLGetVerifyResultCall() {
+ getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
+ }
+
+ Expr getSSLArgument() { result = getArgument(0) }
+}
+
+/**
+ * Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
+ * `SSL_get_verify_result` entering `node`.
+ */
+predicate resultIsChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
+ exists(Expr ssl, SSLGetVerifyResultCall check |
+ ssl = globalValueNumber(getCertCall.getSSLArgument()).getAnExpr() and
+ ssl = check.getSSLArgument() and
+ node = check
+ )
+}
+
+/**
+ * Holds if the certificate returned by `SSL_get_peer_certificate` is found to be
+ * `0` on the edge `node1` to `node2`.
+ */
+predicate certIsZero(
+ SSLGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
+) {
+ exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
+ exists(GuardCondition guard, Expr zero |
+ zero.getValue().toInt() = 0 and
+ node1 = guard and
+ (
+ // if (cert == zero) {
+ guard.comparesEq(cert, zero, 0, true, true) and
+ node2 = guard.getATrueSuccessor()
+ or
+ // if (cert != zero) { }
+ guard.comparesEq(cert, zero, 0, false, true) and
+ node2 = guard.getAFalseSuccessor()
+ )
+ )
+ or
+ (
+ // if (cert) { }
+ node1 = cert
+ or
+ // if (!cert) {
+ node1.(NotExpr).getAChild() = cert
+ ) and
+ node2 = node1.getASuccessor() and
+ not cert.(GuardCondition).controls(node2, true) // cert may be false
+ )
+}
+
+/**
+ * Holds if the SSL object passed into `SSL_get_peer_certificate` has not been checked with
+ * `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
+ * `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
+ */
+predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
+ // cert is not checked at the call to `SSL_get_peer_certificate`
+ node = getCertCall
+ or
+ exists(BasicBlock bb, int pos |
+ // flow to end of a `BasicBlock`
+ certNotChecked(getCertCall, bb.getNode(pos)) and
+ node = bb.getEnd() and
+ // check for barrier node
+ not exists(int pos2 |
+ pos2 > pos and
+ resultIsChecked(getCertCall, bb.getNode(pos2))
+ )
+ )
+ or
+ exists(BasicBlock pred, BasicBlock bb |
+ // flow from the end of one `BasicBlock` to the beginning of a successor
+ certNotChecked(getCertCall, pred.getEnd()) and
+ bb = pred.getASuccessor() and
+ node = bb.getStart() and
+ // check for barrier bb
+ not certIsZero(getCertCall, pred.getEnd(), bb.getStart())
+ )
+}
+
+from SSLGetPeerCertificateCall getCertCall, ControlFlowNode node
+where
+ certNotChecked(getCertCall, node) and
+ node instanceof Function // (function exit)
+select getCertCall,
+ "This " + getCertCall.toString() + " is not followed by a call to SSL_get_verify_result."
diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedBad.cpp b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedBad.cpp
new file mode 100644
index 00000000000..b24b9a790a4
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedBad.cpp
@@ -0,0 +1,5 @@
+// ...
+
+X509 *cert = SSL_get_peer_certificate(ssl); // BAD (SSL_get_verify_result is never called)
+
+// ...
\ No newline at end of file
diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedGood.cpp b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedGood.cpp
new file mode 100644
index 00000000000..af2c9207598
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedGood.cpp
@@ -0,0 +1,9 @@
+// ...
+
+X509 *cert = SSL_get_peer_certificate(ssl); // GOOD
+if (cert)
+{
+ result = SSL_get_verify_result(ssl);
+ if (result == X509_V_OK)
+ {
+ // ...
\ No newline at end of file
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql
index 62bd05d95aa..1d42f69de92 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql
@@ -8,6 +8,7 @@
* @precision high
* @id cpp/cleartext-storage-file
* @tags security
+ * external/cwe/cwe-260
* external/cwe/cwe-313
*/
diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll
index 4739c7ad5cf..29f519163cc 100644
--- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll
+++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll
@@ -84,8 +84,8 @@ class ParameterNullCheck extends ParameterCheck {
p.getFunction() instanceof InitializationFunction and
p.getType().getUnspecifiedType() instanceof PointerType and
exists(VariableAccess va | va = p.getAnAccess() |
- nullSuccessor = getATrueSuccessor() and
- notNullSuccessor = getAFalseSuccessor() and
+ nullSuccessor = this.getATrueSuccessor() and
+ notNullSuccessor = this.getAFalseSuccessor() and
(
va = this.(NotExpr).getOperand() or
va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
@@ -95,8 +95,8 @@ class ParameterNullCheck extends ParameterCheck {
.getAnOperand()
)
or
- nullSuccessor = getAFalseSuccessor() and
- notNullSuccessor = getATrueSuccessor() and
+ nullSuccessor = this.getAFalseSuccessor() and
+ notNullSuccessor = this.getATrueSuccessor() and
(
va = this or
va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
@@ -132,7 +132,7 @@ class ValidatedExternalCondInitFunction extends ExternalData {
ValidatedExternalCondInitFunction() { this.getDataPath().matches("%cond-init%.csv") }
predicate isExternallyVerified(Function f, int param) {
- functionSignature(f, getField(1), getField(2)) and param = getFieldAsInt(3)
+ functionSignature(f, this.getField(1), this.getField(2)) and param = this.getFieldAsInt(3)
}
}
@@ -193,7 +193,7 @@ class InitializationFunction extends Function {
.getAnOverridingFunction+()
.(InitializationFunction)
.initializedParameter() or
- getParameter(i) = any(InitializationFunctionCall c).getAnInitParameter()
+ this.getParameter(i) = any(InitializationFunctionCall c).getAnInitParameter()
)
or
// If we have no definition, we look at SAL annotations
@@ -227,7 +227,7 @@ class InitializationFunction extends Function {
result = getAnInitializedArgument(any(Call c))
or
exists(IfStmt check | result = check.getCondition().getAChild*() |
- paramReassignmentCondition(check)
+ this.paramReassignmentCondition(check)
)
)
or
@@ -249,15 +249,15 @@ class InitializationFunction extends Function {
/** Holds if `n` can be reached without the parameter at `index` being reassigned. */
predicate paramNotReassignedAt(ControlFlowNode n, int index, Context c) {
- c = getAContext(index) and
+ c = this.getAContext(index) and
(
not exists(this.getEntryPoint()) and index = i and n = this
or
n = this.getEntryPoint() and index = i
or
- exists(ControlFlowNode mid | paramNotReassignedAt(mid, index, c) |
+ exists(ControlFlowNode mid | this.paramNotReassignedAt(mid, index, c) |
n = mid.getASuccessor() and
- not n = paramReassignment(index) and
+ not n = this.paramReassignment(index) and
/*
* Ignore successor edges where the parameter is null, because it is then confirmed to be
* initialized.
@@ -265,7 +265,7 @@ class InitializationFunction extends Function {
not exists(ParameterNullCheck nullCheck |
nullCheck = mid and
- nullCheck = getANullCheck(index) and
+ nullCheck = this.getANullCheck(index) and
n = nullCheck.getNullSuccessor()
) and
/*
@@ -281,13 +281,13 @@ class InitializationFunction extends Function {
/** Gets a null-check on the parameter at `index`. */
private ParameterNullCheck getANullCheck(int index) {
- getParameter(index) = result.getParameter()
+ this.getParameter(index) = result.getParameter()
}
/** Gets a parameter which is not at the given index. */
private Parameter getOtherParameter(int index) {
index = i and
- result = getAParameter() and
+ result = this.getAParameter() and
not result.getIndex() = index
}
@@ -306,10 +306,10 @@ class InitializationFunction extends Function {
if
strictcount(Parameter p |
exists(Context c | c = ParamNull(p) or c = ParamNotNull(p)) and
- p = getOtherParameter(index)
+ p = this.getOtherParameter(index)
) = 1
then
- exists(Parameter p | p = getOtherParameter(index) |
+ exists(Parameter p | p = this.getOtherParameter(index) |
result = ParamNull(p) or result = ParamNotNull(p)
)
else
@@ -424,8 +424,8 @@ class ConditionalInitializationCall extends FunctionCall {
/** Gets the argument passed for the given parameter to this call. */
Expr getArgumentForParameter(Parameter p) {
- p = getTarget().getAParameter() and
- result = getArgument(p.getIndex())
+ p = this.getTarget().getAParameter() and
+ result = this.getArgument(p.getIndex())
}
/**
@@ -442,7 +442,7 @@ class ConditionalInitializationCall extends FunctionCall {
context = ParamNotNull(otherP) or
context = ParamNull(otherP)
|
- otherArg = getArgumentForParameter(otherP) and
+ otherArg = this.getArgumentForParameter(otherP) and
(otherArg instanceof AddressOfExpr implies context = ParamNotNull(otherP)) and
(otherArg.getType() instanceof ArrayType implies context = ParamNotNull(otherP)) and
(otherArg.getValue() = "0" implies context = ParamNull(otherP))
@@ -511,8 +511,8 @@ class ConditionalInitializationCall extends FunctionCall {
)
)
or
- exists(ControlFlowNode mid | mid = uncheckedReaches(var) |
- not mid = getStatusVariable().getAnAccess() and
+ exists(ControlFlowNode mid | mid = this.uncheckedReaches(var) |
+ not mid = this.getStatusVariable().getAnAccess() and
not mid = var.getAnAccess() and
not exists(VariableAccess write | result = write and write = var.getAnAccess() |
write = any(AssignExpr a).getLValue() or
diff --git a/cpp/ql/src/Security/CWE/CWE-457/UninitializedVariables.qll b/cpp/ql/src/Security/CWE/CWE-457/UninitializedVariables.qll
index 4289f66e21d..e9c67bd846c 100644
--- a/cpp/ql/src/Security/CWE/CWE-457/UninitializedVariables.qll
+++ b/cpp/ql/src/Security/CWE/CWE-457/UninitializedVariables.qll
@@ -44,7 +44,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
// Find a call that conditionally initializes this variable
hasConditionalInitialization(f, call, this, initAccess, e) and
// Ignore cases where the variable is assigned prior to the call
- not reaches(getAnAssignedValue(), initAccess) and
+ not reaches(this.getAnAssignedValue(), initAccess) and
// Ignore cases where the variable is assigned field-wise prior to the call.
not exists(FieldAccess fa |
exists(Assignment a |
@@ -56,7 +56,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
) and
// Ignore cases where the variable is assigned by a prior call to an initialization function
not exists(Call c |
- getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
+ this.getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
reaches(c, initAccess)
) and
/*
@@ -64,7 +64,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
* the CFG, but should always be considered as initialized, so exclude them.
*/
- not exists(getInitializer().getExpr())
+ not exists(this.getInitializer().getExpr())
}
/**
@@ -90,7 +90,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
// Variable associated with this particular call
call = initializingCall and
// Access is a meaningful read access
- result = getAReadAccess() and
+ result = this.getAReadAccess() and
// Which occurs after the call
reaches(call, result) and
/*
@@ -124,7 +124,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
call = initializingCall and
initializingFunction = f and
e = evidence and
- result = getAReadAccessAfterCall(initializingCall) and
+ result = this.getAReadAccessAfterCall(initializingCall) and
(
// Access is risky because status return code ignored completely
call instanceof ExprInVoidContext
@@ -148,7 +148,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
call = initializingCall and
initializingFunction = f and
e = evidence and
- result = getAReadAccessAfterCall(initializingCall) and
+ result = this.getAReadAccessAfterCall(initializingCall) and
exists(LocalVariable status, Assignment a |
a.getRValue() = call and
call = status.getAnAssignedValue() and
@@ -184,7 +184,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
ConditionalInitializationFunction initializingFunction,
ConditionalInitializationCall initializingCall, Evidence evidence
) {
- result = getARiskyAccessBeforeStatusCheck(initializingFunction, initializingCall, evidence) or
- result = getARiskyAccessWithNoStatusCheck(initializingFunction, initializingCall, evidence)
+ result = this.getARiskyAccessBeforeStatusCheck(initializingFunction, initializingCall, evidence) or
+ result = this.getARiskyAccessWithNoStatusCheck(initializingFunction, initializingCall, evidence)
}
}
diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql
index b9176af1c68..9a0b9bef8ed 100644
--- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql
+++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql
@@ -31,15 +31,15 @@ abstract class SystemData extends Element {
*/
Expr getAnExprIndirect() {
// direct SystemData
- result = getAnExpr() or
+ result = this.getAnExpr() or
// flow via global or member variable (conservative approximation)
- result = getAnAffectedVar().getAnAccess() or
+ result = this.getAnAffectedVar().getAnAccess() or
// flow via stack variable
- definitionUsePair(_, getAnExprIndirect(), result) or
- useUsePair(_, getAnExprIndirect(), result) or
- useUsePair(_, result, getAnExprIndirect()) or
+ definitionUsePair(_, this.getAnExprIndirect(), result) or
+ useUsePair(_, this.getAnExprIndirect(), result) or
+ useUsePair(_, result, this.getAnExprIndirect()) or
// flow from assigned value to assignment expression
- result.(AssignExpr).getRValue() = getAnExprIndirect()
+ result.(AssignExpr).getRValue() = this.getAnExprIndirect()
}
/**
diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql
index 07a7ef1de9b..dcd0cf11dc4 100644
--- a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql
+++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql
@@ -67,16 +67,16 @@ class IFStream extends Type {
*/
class CinVariable extends NamespaceVariable {
CinVariable() {
- getName() = ["cin", "wcin"] and
- getNamespace().getName() = "std"
+ this.getName() = ["cin", "wcin"] and
+ this.getNamespace().getName() = "std"
}
}
/** A call to `std::operator>>`. */
class OperatorRShiftCall extends FunctionCall {
OperatorRShiftCall() {
- getTarget().getNamespace().getName() = "std" and
- getTarget().hasName("operator>>")
+ this.getTarget().getNamespace().getName() = "std" and
+ this.getTarget().hasName("operator>>")
}
/*
@@ -87,15 +87,15 @@ class OperatorRShiftCall extends FunctionCall {
*/
Expr getSource() {
- if getTarget() instanceof MemberFunction
- then result = getQualifier()
- else result = getArgument(0)
+ if this.getTarget() instanceof MemberFunction
+ then result = this.getQualifier()
+ else result = this.getArgument(0)
}
Expr getDest() {
- if getTarget() instanceof MemberFunction
- then result = getArgument(0)
- else result = getArgument(1)
+ if this.getTarget() instanceof MemberFunction
+ then result = this.getArgument(0)
+ else result = this.getArgument(1)
}
}
@@ -119,7 +119,7 @@ abstract class PotentiallyDangerousInput extends Expr {
* Gets the width restriction that applies to the input stream
* for this expression, if any.
*/
- Expr getWidth() { result = getPreviousAccess().getWidthAfter() }
+ Expr getWidth() { result = this.getPreviousAccess().getWidthAfter() }
private Expr getWidthSetHere() {
exists(FunctionCall widthCall |
@@ -154,11 +154,11 @@ abstract class PotentiallyDangerousInput extends Expr {
* after this expression, if any.
*/
Expr getWidthAfter() {
- result = getWidthSetHere()
+ result = this.getWidthSetHere()
or
- not exists(getWidthSetHere()) and
- not isWidthConsumedHere() and
- result = getWidth()
+ not exists(this.getWidthSetHere()) and
+ not this.isWidthConsumedHere() and
+ result = this.getWidth()
}
}
diff --git a/cpp/ql/src/change-notes/released/0.0.4.md b/cpp/ql/src/change-notes/released/0.0.4.md
new file mode 100644
index 00000000000..09ad248a4f9
--- /dev/null
+++ b/cpp/ql/src/change-notes/released/0.0.4.md
@@ -0,0 +1,5 @@
+## 0.0.4
+
+### New Queries
+
+* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.
diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml
new file mode 100644
index 00000000000..ec411a674bc
--- /dev/null
+++ b/cpp/ql/src/codeql-pack.release.yml
@@ -0,0 +1,2 @@
+---
+lastReleaseVersion: 0.0.4
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql b/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql
index 9d2faf793c5..3c079728bcc 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-273/PrivilegeDroppingOutoforder.ql
@@ -21,9 +21,9 @@ predicate argumentMayBeRoot(Expr e) {
class SetuidLikeFunctionCall extends FunctionCall {
SetuidLikeFunctionCall() {
- (getTarget().hasGlobalName("setuid") or getTarget().hasGlobalName("setresuid")) and
+ (this.getTarget().hasGlobalName("setuid") or this.getTarget().hasGlobalName("setresuid")) and
// setuid/setresuid with the root user are false positives.
- not argumentMayBeRoot(getArgument(0))
+ not argumentMayBeRoot(this.getArgument(0))
}
}
@@ -44,7 +44,7 @@ class SetuidLikeWrapperCall extends FunctionCall {
class CallBeforeSetuidFunctionCall extends FunctionCall {
CallBeforeSetuidFunctionCall() {
- getTarget()
+ this.getTarget()
.hasGlobalName([
"setgid", "setresgid",
// Compatibility may require skipping initgroups and setgroups return checks.
@@ -52,7 +52,7 @@ class CallBeforeSetuidFunctionCall extends FunctionCall {
"initgroups", "setgroups"
]) and
// setgid/setresgid/etc with the root group are false positives.
- not argumentMayBeRoot(getArgument(0))
+ not argumentMayBeRoot(this.getArgument(0))
}
}
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
index cf0afc64013..dda2e3b2148 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
@@ -24,7 +24,7 @@ class CallMayNotReturn extends FunctionCall {
not exists(this.(ControlFlowNode).getASuccessor())
or
// call to another function that may not return
- exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
+ exists(CallMayNotReturn exit | this.getTarget() = exit.getEnclosingFunction())
}
}
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-703/FindIncorrectlyUsedExceptions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-703/FindIncorrectlyUsedExceptions.ql
index 34e055534e6..a88cd107b33 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-703/FindIncorrectlyUsedExceptions.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-703/FindIncorrectlyUsedExceptions.ql
@@ -38,13 +38,7 @@ where
fc.getTargetType().(Class).getABaseClass+().hasGlobalOrStdName("exception") or
fc.getTargetType().(Class).getABaseClass+().hasGlobalOrStdName("CException")
) and
+ fc instanceof ExprInVoidContext and
not fc.isInMacroExpansion() and
- not exists(ThrowExpr texp | fc.getEnclosingStmt() = texp.getEnclosingStmt()) and
- not exists(FunctionCall fctmp | fctmp.getAnArgument() = fc) and
- not fc instanceof ConstructorDirectInit and
- not fc.getEnclosingStmt() instanceof DeclStmt and
- not fc instanceof ConstructorDelegationInit and
- not fc.getParent() instanceof Initializer and
- not fc.getParent() instanceof AllocationExpr and
- msg = "This object does not generate an exception."
+ msg = "Object creation of exception type on stack. Did you forget the throw keyword?"
select fc, msg
diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql
index b1eab42af37..380751b5467 100644
--- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql
+++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql
@@ -118,7 +118,7 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
}
class Resource extends MemberVariable {
- Resource() { not isStatic() }
+ Resource() { not this.isStatic() }
// Check that an expr is somewhere in this class - does not have to be a constructor
predicate inSameClass(Expr e) {
@@ -129,7 +129,7 @@ class Resource extends MemberVariable {
f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType()
or
exists(Function mid, FunctionCall fc |
- calledFromDestructor(mid) and
+ this.calledFromDestructor(mid) and
fc.getEnclosingFunction() = mid and
fc.getTarget() = f and
f.getDeclaringType() = this.getDeclaringType()
@@ -137,7 +137,7 @@ class Resource extends MemberVariable {
}
predicate inDestructor(Expr e) {
- exists(Function f | f = e.getEnclosingFunction() | calledFromDestructor(f))
+ exists(Function f | f = e.getEnclosingFunction() | this.calledFromDestructor(f))
}
predicate acquisitionWithRequiredKind(Assignment acquireAssign, string kind) {
diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml
index 8010b3fe73f..51761e13365 100644
--- a/cpp/ql/src/qlpack.yml
+++ b/cpp/ql/src/qlpack.yml
@@ -1,5 +1,6 @@
name: codeql/cpp-queries
-version: 0.0.2
+version: 0.0.5-dev
+groups: cpp
dependencies:
codeql/cpp-all: "*"
codeql/suite-helpers: "*"
diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql
index 4fbfed1706d..0d110e67fa1 100644
--- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql
+++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql
@@ -29,7 +29,8 @@ class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall {
class SelfSub extends SimpleRangeAnalysisExpr, SubExpr {
SelfSub() {
- getLeftOperand().(VariableAccess).getTarget() = getRightOperand().(VariableAccess).getTarget()
+ this.getLeftOperand().(VariableAccess).getTarget() =
+ this.getRightOperand().(VariableAccess).getTarget()
}
override float getLowerBounds() { result = 0 }
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-703/semmle/tests/FindIncorrectlyUsedExceptions.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-703/semmle/tests/FindIncorrectlyUsedExceptions.expected
index f4a2269ec67..af032eb387e 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-703/semmle/tests/FindIncorrectlyUsedExceptions.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-703/semmle/tests/FindIncorrectlyUsedExceptions.expected
@@ -1,3 +1,3 @@
-| test.cpp:35:3:35:33 | call to runtime_error | This object does not generate an exception. |
+| test.cpp:35:3:35:33 | call to runtime_error | Object creation of exception type on stack. Did you forget the throw keyword? |
| test.cpp:41:3:41:11 | call to funcTest1 | There is an exception in the function that requires your attention. |
| test.cpp:42:3:42:9 | call to DllMain | DllMain contains an exeption not wrapped in a try..catch block. |
diff --git a/cpp/ql/test/qlpack.yml b/cpp/ql/test/qlpack.yml
index 5ffadebf8f4..d378db20782 100644
--- a/cpp/ql/test/qlpack.yml
+++ b/cpp/ql/test/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-tests
-version: 0.0.2
+groups: [cpp, test]
dependencies:
codeql/cpp-all: "*"
codeql/cpp-queries: "*"
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp
index 0fbd2643404..7aa83440fd5 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp
+++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp
@@ -20,3 +20,22 @@ bool compareValues() {
bool callCompareValues() {
return compareValues