diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index 4cfaaf8981b3..df14cafd1527 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -82,6 +82,16 @@ module OverflowDestinationConfig implements DataFlow::ConfigSig { nodeIsBarrierEqualityCandidate(node, access, checkedVar) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(FunctionCall fc | result = fc.getLocation() | + sourceSized(fc, sink.asIndirectConvertedExpr()) + ) + } } module OverflowDestination = TaintTracking::Global; diff --git a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql index 62c3c98e197c..34817ff92295 100644 --- a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql +++ b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql @@ -168,6 +168,19 @@ module NonConstFlowConfig implements DataFlow::ConfigSig { cannotContainString(t) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + result = sink.getLocation() + or + exists(FormattingFunctionCall call, Expr formatString | result = call.getLocation() | + isSinkImpl(sink, formatString) and + call.getArgument(call.getFormatParameterIndex()) = formatString + ) + } } module NonConstFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index 3cff86412e49..863fd1e61203 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -215,6 +215,10 @@ private module LeapYearCheckConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument()) } + + predicate observeDiffInformedIncrementalMode() { + none() // only used negatively in UncheckedLeapYearAfterYearModification.ql + } } module LeapYearCheckFlow = DataFlow::Global; @@ -285,6 +289,14 @@ private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::C aexpr.getLValue() = fa ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + result = source.asExpr().getLocation() + } + + Location getASelectedSinkLocation(DataFlow::Node sink) { result = sink.asExpr().getLocation() } } module PossibleYearArithmeticOperationCheckFlow = diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll index f0876800874c..5bc4ac2e2288 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll @@ -51,6 +51,10 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } + + predicate observeDiffInformedIncrementalMode() { + none() // risky since used in library: normal use in UntrustedDataToExternalApi.ql; used via ExternalApiUsedWithUntrustedData (no location) in CountUntrustedDataToExternalAPI.ql + } } module UntrustedDataToExternalApiFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll index d094439951f2..e0a037efd144 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll @@ -46,6 +46,10 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } + + predicate observeDiffInformedIncrementalMode() { + none() // risky since used in library: normal use in IRUntrustedDataToExternalApi.ql; used via ExternalApiUsedWithUntrustedData (no location) in IRCountUntrustedDataToExternalAPI.ql + } } module UntrustedDataToExternalApiFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 94a9cacf9f49..1a15f6c3a152 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -93,6 +93,12 @@ module TaintedPathConfig implements DataFlow::ConfigSig { // make sinks barriers so that we only report the closest instance isSink(node) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + result = sink.asIndirectArgument().getLocation() + } } module TaintedPath = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql index a609724937aa..1098656f7a20 100644 --- a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql @@ -150,6 +150,17 @@ module ExecTaintConfig implements DataFlow::StateConfigSig { predicate isBarrierOut(DataFlow::Node node) { isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(DataFlow::Node concatResult, Expr command, ExecState state | + result = [concatResult.getLocation(), command.getLocation()] and + isSink(sink, state) and + isSinkImpl(sink, command, _) and + concatResult = state.getOutgoingNode() + ) + } } module ExecTaint = TaintTracking::GlobalWithState; diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index 9b27e95fd658..994aba733d23 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -39,6 +39,12 @@ module Config implements DataFlow::ConfigSig { or node.asCertainDefinition().getUnspecifiedType() instanceof ArithmeticType } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + exists(QueryString query | result = query.getLocation() | query = source.asIndirectExpr()) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 0ea4ce2e95f4..5a823b8672c5 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -54,6 +54,12 @@ module SqlTaintedConfig implements DataFlow::ConfigSig { sql.barrierSqlArgument(input, _) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(Expr taintedArg | result = taintedArg.getLocation() | taintedArg = asSinkExpr(sink)) + } } module SqlTainted = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql index ec3543c19928..2cce72bc2ae8 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql @@ -124,6 +124,12 @@ module Config implements DataFlow::ConfigSig { // Block flow if the node is guarded by any <, <= or = operations. node = DataFlow::BarrierGuard::getABarrierNode() } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(BufferWrite bw | result = bw.getLocation() | isSink(sink, bw, _)) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql index 9b595657fce9..2f051776dbe2 100644 --- a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql @@ -43,6 +43,12 @@ private module Config implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { isSink(sink, _) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(VariableAccess va | result = va.getLocation() | isSink(sink, va)) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql index c9efaf9f6952..86806c0b7762 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql @@ -106,6 +106,12 @@ module Config implements DataFlow::ConfigSig { not iTo instanceof PointerArithmeticInstruction ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(Expr e | result = e.getLocation() | isSink(sink, _, e)) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 54c3b013471a..64705f078c69 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -120,6 +120,12 @@ module UncontrolledArithConfig implements DataFlow::ConfigSig { // block unintended flow to pointers node.asExpr().getUnspecifiedType() instanceof PointerType } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + result = getExpr(source).getLocation() + } } module UncontrolledArith = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql index 15fd2cbca15f..50cef092600b 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql @@ -113,6 +113,12 @@ module Config implements DataFlow::ConfigSig { not iTo instanceof PointerArithmeticInstruction ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(VariableAccess va | result = va.getLocation() | isSink(sink, va, _)) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 6307ddf5fe63..0149f483cc12 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -91,6 +91,12 @@ module TaintedAllocationSizeConfig implements DataFlow::ConfigSig { // to duplicate results) any(HeuristicAllocationFunction f).getAParameter() = node.asParameter() } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(Expr alloc | result = alloc.getLocation() | allocSink(alloc, sink)) + } } module TaintedAllocationSize = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql index ada0180668e0..74386b30bbab 100644 --- a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +++ b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql @@ -72,6 +72,12 @@ module Config implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { isSource(source, _) } predicate isSink(DataFlow::Node sink) { isSink(sink, _) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(Expr condition | result = condition.getLocation() | isSink(sink, condition)) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql index 8a3c2f3664d6..379c20f51baf 100644 --- a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql +++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql @@ -31,6 +31,14 @@ module VerifyResultConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { exists(GuardCondition guard | guard.getAChild*() = sink.asExpr()) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(GuardCondition guard | result = guard.getLocation() | + guard.comparesEq(sink.asExpr(), _, 0, false, _) + ) + } } module VerifyResult = DataFlow::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index f2754c5811f0..c671ad5af7f2 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -47,6 +47,12 @@ module ToBufferConfig implements DataFlow::ConfigSig { } predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(SensitiveBufferWrite w | result = w.getLocation() | isSinkImpl(sink, w)) + } } module ToBufferFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql index c04ceae7adad..6aff19ceb4af 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql @@ -31,6 +31,16 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node sourceNode) { + exists(SensitiveExpr source | result = source.getLocation() | isSourceImpl(sourceNode, source)) + } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(FileWrite w | result = w.getLocation() | isSinkImpl(sink, w, _)) + } } module FromSensitiveFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 09db3f216029..10bb10d6a2bb 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -245,6 +245,14 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { // sources to not get path duplication. isSource(node) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(NetworkSendRecv networkSendRecv | result = networkSendRecv.getLocation() | + isSinkSendRecv(sink, networkSendRecv) + ) + } } module FromSensitiveFlow = TaintTracking::Global; @@ -266,6 +274,10 @@ module ToEncryptionConfig implements DataFlow::ConfigSig { // sources to not get path duplication. isSource(node) } + + predicate observeDiffInformedIncrementalMode() { + none() // only used negatively + } } module ToEncryptionFlow = TaintTracking::Global; @@ -281,6 +293,10 @@ module FromEncryptionConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } + + predicate observeDiffInformedIncrementalMode() { + none() // only used negatively + } } module FromEncryptionFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index 0c060befeff5..a6f567600f9d 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -123,6 +123,20 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { content.(DataFlow::FieldContent).getField() = getRecField(t.stripType()) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + exists(SensitiveExpr sensitive | result = sensitive.getLocation() | + isSourceImpl(source, sensitive) + ) + } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(SqliteFunctionCall sqliteCall | result = sqliteCall.getLocation() | + isSinkImpl(sink, sqliteCall, _) + ) + } } module FromSensitiveFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql index 423ed57dd98f..d12340035bde 100644 --- a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +++ b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql @@ -87,6 +87,14 @@ module HttpStringToUrlOpenConfig implements DataFlow::ConfigSig { sink.asIndirectExpr() = fc.getArgument(3) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + result = source.asIndirectExpr().getLocation() + } + + Location getASelectedSinkLocation(DataFlow::Node sink) { none() } } module HttpStringToUrlOpen = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql index 3cc10b7ad19c..9f75475854dc 100644 --- a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -44,6 +44,12 @@ module KeyStrengthFlowConfig implements DataFlow::ConfigSig { exists(getMinimumKeyStrength(name, param)) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(FunctionCall fc | result = fc.getLocation() | sink.asExpr() = fc.getArgument(_)) + } } module KeyStrengthFlow = DataFlow::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql index 11d628c1affa..c386cb1da4d8 100644 --- a/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql +++ b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql @@ -145,6 +145,18 @@ module Config implements DataFlow::StateConfigSig { // ``` result instanceof DataFlow::FeatureHasSinkCallContext } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(DataFlow::Node mid, FlowState state | result = mid.getLocation() | + destroyedToBeginSink(sink) and + isSink(sink, state) and + state = Config::DestroyedToBegin(mid) + ) + } } module Flow = DataFlow::GlobalWithState; diff --git a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql index 2703f819b546..f0851b7d8075 100644 --- a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql @@ -62,6 +62,16 @@ module NullAppNameCreateProcessFunctionConfig implements DataFlow::ConfigSig { val = call.getArgument(call.getApplicationNameArgumentId()) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(CreateProcessFunctionCall call | result = call.getLocation() | + sink.asExpr() = call.getArgument(call.getApplicationNameArgumentId()) + ) + } } module NullAppNameCreateProcessFunction = DataFlow::Global; @@ -82,6 +92,16 @@ module QuotedCommandInCreateProcessFunctionConfig implements DataFlow::ConfigSig val = call.getArgument(call.getCommandLineArgumentId()) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(CreateProcessFunctionCall call | result = call.getLocation() | + sink.asExpr() = call.getArgument(call.getCommandLineArgumentId()) + ) + } } module QuotedCommandInCreateProcessFunction = diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index 5ed30e19bb32..a0096f410c51 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -37,6 +37,16 @@ module NullDaclConfig implements DataFlow::ConfigSig { val = call.getArgument(2) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(SetSecurityDescriptorDaclFunctionCall call | result = call.getLocation() | + sink.asExpr() = call.getArgument(2) + ) + } } module NullDaclFlow = DataFlow::Global; @@ -68,6 +78,10 @@ module NonNullDaclConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2)) } + + predicate observeDiffInformedIncrementalMode() { + none() // only used negatively + } } module NonNullDaclFlow = DataFlow::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql index 7eaa5df849d4..171fbd26dd93 100644 --- a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +++ b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql @@ -65,6 +65,16 @@ module Config implements DataFlow::ConfigSig { iFrom1 != iFrom2 ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + result = sink.getLocation() + or + exists(Expr raise | result = raise.getLocation() | + sensitiveCondition([sink.asExpr(), sink.asIndirectExpr()], raise) + ) + } } module Flow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql b/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql index acfd27cc45ba..4ca30c3e916a 100644 --- a/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql +++ b/cpp/ql/src/Security/CWE/CWE-843/TypeConfusion.ql @@ -178,6 +178,10 @@ module Config implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(UnsafeCast cast).getUnconverted() } int fieldFlowBranchLimit() { result = 0 } + + predicate observeDiffInformedIncrementalMode() { + none() // used both positively and negatively + } } module Flow = DataFlow::Global; diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql index c38a012b27bf..b7b2de6000ae 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql @@ -183,6 +183,20 @@ module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig { pointerArithOverflow(pai, _) ) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { + exists(Variable v | result = v.getLocation() | isSourceImpl(source, v)) + } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(PointerArithmeticInstruction pai, Instruction deref | + result = [pai, deref].getLocation() and + isInvalidPointerDerefSink2(sink, deref, _) and + isSink(sink, ArrayAddressToDerefConfig::TOverflowArithmetic(pai)) + ) + } } module ArrayAddressToDerefFlow = DataFlow::GlobalWithState; diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql index bfa11e65b067..fbeb4cde5fd1 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql @@ -28,6 +28,14 @@ module DecompressionTaintConfig implements DataFlow::ConfigSig { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { any(DecompressionFlowStep s).isAdditionalFlowStep(node1, node2) } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSourceLocation(DataFlow::Node source) { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(FunctionCall fc | result = [sink.getLocation(), fc.getLocation()] | isSink(fc, sink)) + } } module DecompressionTaint = TaintTracking::Global; diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..082405f9e404 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/CountUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp new file mode 100644 index 000000000000..471ed26cb259 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPISinkExample.cpp @@ -0,0 +1,18 @@ +typedef unsigned long size_t; +typedef size_t FILE; + +char *strcat(char *s1, const char *s2); +char *fgets(char *s, int n, FILE *stream); +char *fputs(const char *s, FILE *stream); + +void do_get(FILE* request, FILE* response) { + char page[1024]; + fgets(page, 1024, request); + + char buffer[1024]; + strcat(buffer, "The page \""); + strcat(buffer, page); + strcat(buffer, "\" was not found."); + + fputs(buffer, response); +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp new file mode 100644 index 000000000000..1641ce3baa0d --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/ExternalAPITaintStepExample.cpp @@ -0,0 +1,18 @@ +typedef unsigned long size_t; +typedef size_t FILE; + +char *strcat(char *s1, const char *s2); +char *fgets(char *s, int n, FILE *stream); +char *fputs(const char *s, FILE *stream); + +void do_get(FILE* request, FILE* response) { + char user_id[1024]; + fgets(user_id, 1024, request); + + char buffer[1024]; + strcat(buffer, "SELECT * FROM user WHERE user_id='"); + strcat(buffer, user_id); + strcat(buffer, "'"); + + // ... +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..81155a9a6375 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/IRCountUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..58f42bec0c84 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.expected @@ -0,0 +1,4 @@ +#select +edges +nodes +subpaths diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..826e00a0263f --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected new file mode 100644 index 000000000000..58f42bec0c84 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.expected @@ -0,0 +1,4 @@ +#select +edges +nodes +subpaths diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref new file mode 100644 index 000000000000..a4c937bd3d8a --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-020/UntrustedDataToExternalAPI.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.cpp new file mode 100644 index 000000000000..57298515793b --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.cpp @@ -0,0 +1,121 @@ +typedef unsigned long size_t; +typedef struct sqlite3 sqlite3; +typedef struct sqlite3_stmt sqlite3_stmt; +typedef struct sqlite3_str sqlite3_str; + +int snprintf(char *str, size_t size, const char *format, ...); +int sqlite3_open(const char *filename, sqlite3 **ppDb); +int sqlite3_close(sqlite3*); +int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*,int,char**,char**), void *, char **errmsg); +int sqlite3_prepare_v2(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail); +int sqlite3_step(sqlite3_stmt*); +int sqlite3_finalize(sqlite3_stmt*); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +sqlite3_str* sqlite3_str_new(sqlite3*); +void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); +char* sqlite3_str_finish(sqlite3_str*); + +#define SQLITE_TRANSIENT ((void(*)(void*))-1) + +// Simulate a sensitive value +const char* getSensitivePassword() { + return "super_secret_password"; +} + +void storePasswordCleartext(sqlite3* db, const char* password) { + // BAD: Storing sensitive data in cleartext + char sql[256]; + // Unsafe: no escaping, for test purposes only + snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", password); // $ Source + char* errMsg = 0; + sqlite3_exec(db, sql, 0, 0, &errMsg); // $ Alert +} + +void storePasswordWithPrepare(sqlite3* db, const char* password) { + // BAD: Storing sensitive data in cleartext using sqlite3_prepare + char sql[256]; + snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", password); // $ Source + sqlite3_stmt* stmt = 0; + sqlite3_prepare_v2(db, sql, -1, &stmt, 0); // $ Alert + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} + +void storePasswordWithBind(sqlite3* db, const char* password) { + // BAD: Storing sensitive data in cleartext using sqlite3_bind_text + const char* sql = "INSERT INTO users(password) VALUES(?);"; + sqlite3_stmt* stmt = 0; + sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); // $ Alert + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} + +void storePasswordWithAppendf(sqlite3_str* pStr, const char* password) { + // BAD: Storing sensitive data in cleartext using sqlite3_str_appendf + sqlite3_str_appendf(pStr, "INSERT INTO users(password) VALUES('%s');", password); // $ Alert +} + +// Example sanitizer: hashes the sensitive value before storage +void hashSensitiveValue(const char* input, char* output, size_t outSize) { + // Dummy hash for illustration (not cryptographically secure) + unsigned int hash = 5381; + for (const char* p = input; *p; ++p) + hash = ((hash << 5) + hash) + (unsigned char)(*p); + snprintf(output, outSize, "%u", hash); +} + +void storeSanitizedPasswordCleartext(sqlite3* db, const char* password) { + // GOOD: Sanitizing sensitive data before storage + char hashed[64]; + hashSensitiveValue(password, hashed, sizeof(hashed)); + char sql[256]; + snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", hashed); + char* errMsg = 0; + sqlite3_exec(db, sql, 0, 0, &errMsg); +} + +void storeSanitizedPasswordWithBind(sqlite3* db, const char* password) { + // GOOD: Sanitizing sensitive data before storage with bind + char hashed[64]; + hashSensitiveValue(password, hashed, sizeof(hashed)); + const char* sql = "INSERT INTO users(password) VALUES(?);"; + sqlite3_stmt* stmt = 0; + sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + sqlite3_bind_text(stmt, 1, hashed, -1, SQLITE_TRANSIENT); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} + +void storeSanitizedPasswordWithAppendf(sqlite3_str* pStr, const char* password) { + // GOOD: Sanitizing sensitive data before storage with appendf + char hashed[64]; + hashSensitiveValue(password, hashed, sizeof(hashed)); + sqlite3_str_appendf(pStr, "INSERT INTO users(password) VALUES('%s');", hashed); +} + +int main() { + sqlite3* db = 0; + sqlite3_open(":memory:", &db); + + // Create table + const char* createTableSQL = "CREATE TABLE users(id INTEGER PRIMARY KEY, password TEXT);"; + sqlite3_exec(db, createTableSQL, 0, 0, 0); + + const char* sensitive = getSensitivePassword(); + + storePasswordCleartext(db, sensitive); + storePasswordWithPrepare(db, sensitive); + storePasswordWithBind(db, sensitive); + storeSanitizedPasswordCleartext(db, sensitive); + storeSanitizedPasswordWithBind(db, sensitive); + + // If sqlite3_str is available + sqlite3_str* pStr = sqlite3_str_new(db); + storePasswordWithAppendf(pStr, sensitive); + storeSanitizedPasswordWithAppendf(pStr, sensitive); + sqlite3_str_finish(pStr); + + sqlite3_close(db); + return 0; +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.expected new file mode 100644 index 000000000000..89a7a2c58265 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.expected @@ -0,0 +1,16 @@ +#select +| CleartextSqliteDatabase.cpp:31:5:31:16 | call to sqlite3_exec | CleartextSqliteDatabase.cpp:29:77:29:84 | password | CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:29:77:29:84 | password | sensitive information | +| CleartextSqliteDatabase.cpp:39:5:39:22 | call to sqlite3_prepare_v2 | CleartextSqliteDatabase.cpp:37:77:37:84 | password | CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:37:77:37:84 | password | sensitive information | +| CleartextSqliteDatabase.cpp:49:5:49:21 | call to sqlite3_bind_text | CleartextSqliteDatabase.cpp:49:32:49:39 | password | CleartextSqliteDatabase.cpp:49:32:49:39 | password | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:49:32:49:39 | password | sensitive information | +| CleartextSqliteDatabase.cpp:56:5:56:23 | call to sqlite3_str_appendf | CleartextSqliteDatabase.cpp:56:76:56:83 | password | CleartextSqliteDatabase.cpp:56:76:56:83 | password | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:56:76:56:83 | password | sensitive information | +edges +| CleartextSqliteDatabase.cpp:29:77:29:84 | password | CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | provenance | TaintFunction | +| CleartextSqliteDatabase.cpp:37:77:37:84 | password | CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | provenance | TaintFunction | +nodes +| CleartextSqliteDatabase.cpp:29:77:29:84 | password | semmle.label | password | +| CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | semmle.label | *sql | +| CleartextSqliteDatabase.cpp:37:77:37:84 | password | semmle.label | password | +| CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | semmle.label | *sql | +| CleartextSqliteDatabase.cpp:49:32:49:39 | password | semmle.label | password | +| CleartextSqliteDatabase.cpp:56:76:56:83 | password | semmle.label | password | +subpaths diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.qlref new file mode 100644 index 000000000000..d5adb06122dd --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-313/CleartextSqliteDatabase.qlref @@ -0,0 +1,4 @@ +query: Security/CWE/CWE-313/CleartextSqliteDatabase.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy