Skip to content

C++: Diff-informed queries: phase 3 (non-trivial locations) #20073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Aug 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
43e99d0
[TEST] C++: CleartextSqliteDatabase: add new test
d10c Jul 15, 2025
448a1ea
[DIFF-INFORMED] C++: OverflowDestination
d10c Jul 15, 2025
fabdf99
[DIFF-INFORMED] C++: ConstantSizeArrayOffByOne
d10c Jul 15, 2025
e382cb5
[DIFF-INFORMED] C++: DecompressionBombs
d10c Jul 15, 2025
2f56baa
[DIFF-INFORMED] C++: NonConstantFormat
d10c Jul 15, 2025
91b9c3e
[DIFF-INFORMED] C++: LeapYear
d10c Jul 16, 2025
a77cab6
[DIFF-INFORMED] C++: TaintedPath
d10c Jul 16, 2025
80da00b
[DIFF-INFORMED] C++: ExecTainted
d10c Jul 16, 2025
36d43a4
[DIFF-INFORMED] C++: CgiXss
d10c Jul 16, 2025
7df09f3
[DIFF-INFORMED] C++: SqlTainted
d10c Jul 16, 2025
f3098e7
[DIFF-INFORMED] C++: UnboundedWrite
d10c Jul 16, 2025
62fa730
[DIFF-INFORMED] C++: ImproperNullTerminationTainted
d10c Jul 16, 2025
861a768
[DIFF-INFORMED] C++: CWE-190/ArithmeticTainted,etc.
d10c Jul 16, 2025
87016f3
[DIFF-INFORMED] C++: AuthenticationBypass
d10c Jul 16, 2025
2191403
[DIFF-INFORMED] C++: SSLResultConflation (has secondary config but pa…
d10c Jul 16, 2025
05df2f2
[DIFF-INFORMED] C++: CWE-311/Cleartext…
d10c Jul 16, 2025
8560868
[DIFF-INFORMED] C++: CleartextSqliteDatabase
d10c Jul 16, 2025
c0c96ea
[DIFF-INFORMED] C++: UseOfHttp
d10c Jul 16, 2025
ec85e55
[DIFF-INFORMED] C++: InsufficientKeySize
d10c Jul 16, 2025
39b430a
[DIFF-INFORMED] C++: IteratorToExpiredContainer
d10c Jul 16, 2025
194d9a9
[DIFF-INFORMED] C++: UnsafeCreateProcessCall
d10c Jul 16, 2025
0c636dd
[DIFF-INFORMED] C++: UnsafeDaclSecurityDescriptor
d10c Jul 16, 2025
5b9e37c
[DIFF-INFORMED] C++: TaintedCondition
d10c Jul 16, 2025
8978820
[DIFF-INFORMED] C++: TypeConfusion
d10c Jul 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cpp/ql/src/Critical/OverflowDestination.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<OverflowDestinationConfig>;
Expand Down
13 changes: 13 additions & 0 deletions cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<NonConstFlowConfig>;
Expand Down
12 changes: 12 additions & 0 deletions cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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<LeapYearCheckConfig>;
Expand Down Expand Up @@ -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 =
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<TaintedPathConfig>;
Expand Down
11 changes: 11 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<ExecTaintConfig>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<SqlTaintedConfig>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ module Config implements DataFlow::ConfigSig {
// Block flow if the node is guarded by any <, <= or = operations.
node = DataFlow::BarrierGuard<lessThanOrEqual/3>::getABarrierNode()
}

predicate observeDiffInformedIncrementalMode() { any() }

Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(BufferWrite bw | result = bw.getLocation() | isSink(sink, bw, _))
}
}

module Flow = TaintTracking::Global<Config>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<UncontrolledArithConfig>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<TaintedAllocationSizeConfig>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
8 changes: 8 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<VerifyResultConfig>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<ToBufferConfig>;
Expand Down
10 changes: 10 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<FromSensitiveConfig>;
Expand Down
16 changes: 16 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<FromSensitiveConfig>;
Expand All @@ -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<ToEncryptionConfig>;
Expand All @@ -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<FromEncryptionConfig>;
Expand Down
14 changes: 14 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<FromSensitiveConfig>;
Expand Down
8 changes: 8 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<HttpStringToUrlOpenConfig>;
Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeyStrengthFlowConfig>;
Expand Down
12 changes: 12 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<Config>;
Expand Down
20 changes: 20 additions & 0 deletions cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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<NullAppNameCreateProcessFunctionConfig>;
Expand All @@ -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 =
Expand Down
Loading