Content-Length: 29628 | pFad | http://github.com/github/codeql/pull/20023.diff

thub.com diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index d776985720af..d7f26dd00513 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1382,16 +1382,89 @@ predicate neverSkipInPathGraph(Node n) { exists(n.asIndirectDefinition()) } -class LambdaCallKind = Unit; +private newtype TLambdaCallKind = + TFunctionPointer() or + TFunctor() + +class LambdaCallKind extends TLambdaCallKind { + predicate isFunctionPointer() { this = TFunctionPointer() } + + predicate isFunctor() { this = TFunctor() } + + string toString() { + this.isFunctionPointer() and + result = "Function pointer kind" + or + this.isFunctor() and + result = "Functor kind" + } +} + +private class ConstructorCallInstruction extends CallInstruction { + Cpp::Class constructedType; + + ConstructorCallInstruction() { + this.getStaticCallTarget().(Cpp::Constructor).getDeclaringType() = constructedType + } + + Cpp::Class getConstructedType() { result = constructedType } +} + +private class OperatorCall extends Cpp::MemberFunction { + OperatorCall() { this.hasName("operator()") } +} + +private predicate isFunctorCreationWithoutConstructor(Node creation, OperatorCall operator) { + exists(UninitializedInstruction init, Instruction dest | + // A construction of an object with no constructor. In this case we use + // the `UninitializedInstruction` as the creation node. + init = creation.asInstruction() and + dest = init.getDestinationAddress() and + not any(ConstructorCallInstruction constructorCall).getThisArgument() = dest and + operator.getDeclaringType() = init.getResultType() + ) + or + // Workaround for an extractor bug. In this snippet: + // ``` + // struct S { }; + // void f(S); + // f(S()); + // ``` + // The expression `S()` is represented as a 0 literal in the database. + exists(ConstantValueInstruction constant | + constant.getValue() = "0" and + creation.asInstruction() = constant and + constant.getResultType() = operator.getDeclaringType() + ) +} + +private predicate isFunctorCreationWithConstructor(Node creation, OperatorCall operator) { + exists(DataFlowCall constructorCall, IndirectionPosition pos | + // A construction of an object with a constructor. In this case we use + // the post-update node of the qualifier + pos.getArgumentIndex() = -1 and + isArgumentNode(creation.(PostUpdateNode).getPreUpdateNode(), constructorCall, pos) and + operator.getDeclaringType() = + constructorCall.asCallInstruction().(ConstructorCallInstruction).getConstructedType() + ) +} /** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { - creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable() and - exists(kind) + kind.isFunctionPointer() and + creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable() + or + kind.isFunctor() and + exists(OperatorCall operator | operator = c.asSourceCallable() | + isFunctorCreationWithoutConstructor(creation, operator) + or + isFunctorCreationWithConstructor(creation, operator) + ) } /** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { + kind.isFunctionPointer() and ( call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() or @@ -1400,8 +1473,15 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { // has a result for `getStaticCallTarget`. not exists(call.getStaticCallTarget()) and call.asCallInstruction().getCallTargetOperand() = receiver.asOperand() - ) and - exists(kind) + ) + or + kind.isFunctor() and + ( + call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() + or + not exists(call.getStaticCallTarget()) and + call.asCallInstruction().getThisArgumentOperand() = receiver.asOperand() + ) } /** Extra data-flow steps needed for lambda flow analysis. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index af5dd4199858..96c18a04ff7b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction { * Gets the variable that is uninitialized. */ final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() } + + /** + * Gets the operand that provides the address of the location to which the + * uninitialized value will be stored. + */ + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } + + /** + * Gets the instruction whose result provides the address of the location to + * which the value will be stored, if an exact definition is available. + */ + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index af5dd4199858..96c18a04ff7b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction { * Gets the variable that is uninitialized. */ final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() } + + /** + * Gets the operand that provides the address of the location to which the + * uninitialized value will be stored. + */ + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } + + /** + * Gets the instruction whose result provides the address of the location to + * which the value will be stored, if an exact definition is available. + */ + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index af5dd4199858..96c18a04ff7b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction { * Gets the variable that is uninitialized. */ final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() } + + /** + * Gets the operand that provides the address of the location to which the + * uninitialized value will be stored. + */ + final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() } + + /** + * Gets the instruction whose result provides the address of the location to + * which the value will be stored, if an exact definition is available. + */ + final Instruction getDestinationAddress() { + result = this.getDestinationAddressOperand().getDef() + } } /** diff --git a/cpp/ql/src/change-notes/2025-07-11-function-objects.md b/cpp/ql/src/change-notes/2025-07-11-function-objects.md new file mode 100644 index 000000000000..48bc71f27ca8 --- /dev/null +++ b/cpp/ql/src/change-notes/2025-07-11-function-objects.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Improved support for dataflow through function objects and lambda expressions. \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected index bf306c28a99d..bf9a4ed28d01 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected @@ -21,13 +21,14 @@ models | 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual | | 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual | | 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual | -| 23 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual | -| 24 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | -| 25 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | -| 26 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | -| 27 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual | +| 23 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual | +| 24 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual | +| 25 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated | +| 26 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual | +| 27 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual | +| 28 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual | edges -| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:27 | +| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:28 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 | | asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 | | asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction | @@ -36,10 +37,10 @@ edges | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | | | asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 | | asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | | -| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:27 | -| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:25 | -| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:24 | -| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:26 | +| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:28 | +| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:26 | +| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:25 | +| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:27 | | test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | | | test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | | | test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 | @@ -51,15 +52,15 @@ edges | test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | | | test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 | | test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | | -| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:25 | +| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:26 | | test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | | | test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 | | test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | | -| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:24 | +| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:25 | | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | | | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 | | test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | | -| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:26 | +| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:27 | | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | | | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 | | test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | | @@ -67,12 +68,33 @@ edges | test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | | | test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | | | test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 | -| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:23 | +| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:24 | | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | | | test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | | | test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | | | test.cpp:56:8:56:16 | call to ymlSource | test.cpp:56:2:56:18 | ... = ... | provenance | Src:MaD:16 | | test.cpp:59:55:59:64 | *& ... [x] | test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | provenance | | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:68:22:68:22 | y | provenance | | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:74:22:74:22 | y | provenance | | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:82:22:82:22 | y | provenance | | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:88:22:88:22 | y | provenance | | +| test.cpp:68:22:68:22 | y | test.cpp:69:11:69:11 | y | provenance | Sink:MaD:1 | +| test.cpp:74:22:74:22 | y | test.cpp:75:11:75:11 | y | provenance | Sink:MaD:1 | +| test.cpp:82:22:82:22 | y | test.cpp:83:11:83:11 | y | provenance | Sink:MaD:1 | +| test.cpp:88:22:88:22 | y | test.cpp:89:11:89:11 | y | provenance | Sink:MaD:1 | +| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:94:10:94:18 | call to ymlSource | provenance | Src:MaD:16 | +| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:97:26:97:26 | x | provenance | | +| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:101:26:101:26 | x | provenance | | +| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:103:63:103:63 | x | provenance | | +| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:104:62:104:62 | x | provenance | | +| test.cpp:97:26:97:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | +| test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | +| test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | +| test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | | @@ -209,6 +231,28 @@ nodes | test.cpp:56:2:56:18 | ... = ... | semmle.label | ... = ... | | test.cpp:56:8:56:16 | call to ymlSource | semmle.label | call to ymlSource | | test.cpp:59:55:59:64 | *& ... [x] | semmle.label | *& ... [x] | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument | +| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument | +| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument | +| test.cpp:68:22:68:22 | y | semmle.label | y | +| test.cpp:69:11:69:11 | y | semmle.label | y | +| test.cpp:74:22:74:22 | y | semmle.label | y | +| test.cpp:75:11:75:11 | y | semmle.label | y | +| test.cpp:82:22:82:22 | y | semmle.label | y | +| test.cpp:83:11:83:11 | y | semmle.label | y | +| test.cpp:88:22:88:22 | y | semmle.label | y | +| test.cpp:89:11:89:11 | y | semmle.label | y | +| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource | +| test.cpp:97:26:97:26 | x | semmle.label | x | +| test.cpp:101:26:101:26 | x | semmle.label | x | +| test.cpp:103:63:103:63 | x | semmle.label | x | +| test.cpp:104:62:104:62 | x | semmle.label | x | | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA | | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml index 12dbf7d4cd23..f0df3e749e69 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml +++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml @@ -16,4 +16,5 @@ extensions: - ["", "", False, "ymlStepManual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] - ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] \ No newline at end of file + - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"] + - ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"] \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected index 7e5b714765bd..0cc01c8165e1 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected @@ -9,3 +9,7 @@ | test.cpp:33:10:33:11 | z2 | test-sink | | test.cpp:36:10:36:11 | z3 | test-sink | | test.cpp:48:16:48:16 | x | test-sink | +| test.cpp:69:11:69:11 | y | test-sink | +| test.cpp:75:11:75:11 | y | test-sink | +| test.cpp:83:11:83:11 | y | test-sink | +| test.cpp:89:11:89:11 | y | test-sink | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected index b0f52caf00ca..401fffdbd594 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected +++ b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected @@ -1,6 +1,7 @@ | asio_streams.cpp:87:34:87:44 | read_until output argument | remote | | test.cpp:10:10:10:18 | call to ymlSource | local | | test.cpp:56:8:56:16 | call to ymlSource | local | +| test.cpp:94:10:94:18 | call to ymlSource | local | | windows.cpp:22:15:22:29 | *call to GetCommandLineA | local | | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local | | windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local | diff --git a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp index d40ee556a63f..f357b934b2fb 100644 --- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp @@ -58,3 +58,48 @@ int test_pthread_create() { pthread_t threadId; pthread_create(&threadId, nullptr, myThreadFunction, (void *)&s); } + +template +void callWithArgument(F f, int x); + +struct StructWithOperatorCall_has_constructor { + StructWithOperatorCall_has_constructor(); + + void operator()(int y) { + ymlSink(y); // $ ir + } +}; + +struct StructWithOperatorCall_no_constructor { + void operator()(int y) { + ymlSink(y); // $ ir + } +}; + +struct StructWithOperatorCall_has_constructor_2 { + StructWithOperatorCall_has_constructor_2(); + + void operator()(int y) { + ymlSink(y); // $ ir + } +}; + +struct StructWithOperatorCall_no_constructor_2 { + void operator()(int y) { + ymlSink(y); // $ ir + } +}; + +void test_callWithArgument() { + int x = ymlSource(); + { + StructWithOperatorCall_has_constructor func; + callWithArgument(func, x); + } + { + StructWithOperatorCall_no_constructor func; + callWithArgument(func, x); + } + callWithArgument(StructWithOperatorCall_has_constructor_2(), x); + callWithArgument(StructWithOperatorCall_no_constructor_2(), x); +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 1bf719e630ee..e19f34eb2170 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -7777,17 +7777,24 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future | thread.cpp:24:5:24:5 | s | thread.cpp:26:38:26:38 | s | | | thread.cpp:24:5:24:5 | s | thread.cpp:27:37:27:37 | s | | | thread.cpp:24:5:24:5 | s | thread.cpp:28:38:28:38 | s | | +| thread.cpp:24:5:24:5 | s | thread.cpp:32:7:32:7 | s | | | thread.cpp:25:3:25:3 | s [post update] | thread.cpp:26:38:26:38 | s | | | thread.cpp:25:3:25:3 | s [post update] | thread.cpp:27:37:27:37 | s | | | thread.cpp:25:3:25:3 | s [post update] | thread.cpp:28:38:28:38 | s | | +| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:32:7:32:7 | s | | | thread.cpp:25:3:25:16 | ... = ... | thread.cpp:25:5:25:5 | x [post update] | | | thread.cpp:25:9:25:14 | call to source | thread.cpp:25:3:25:16 | ... = ... | | -| thread.cpp:26:18:26:39 | call to thread | thread.cpp:29:1:29:1 | t1 | | +| thread.cpp:26:18:26:39 | call to thread | thread.cpp:33:1:33:1 | t1 | | | thread.cpp:26:38:26:38 | s | thread.cpp:26:37:26:38 | & ... | | -| thread.cpp:27:18:27:38 | call to thread | thread.cpp:29:1:29:1 | t2 | | +| thread.cpp:27:18:27:38 | call to thread | thread.cpp:33:1:33:1 | t2 | | | thread.cpp:27:37:27:37 | ref arg s | thread.cpp:28:38:28:38 | s | | -| thread.cpp:28:18:28:43 | call to thread | thread.cpp:29:1:29:1 | t3 | | +| thread.cpp:27:37:27:37 | ref arg s | thread.cpp:32:7:32:7 | s | | +| thread.cpp:28:18:28:43 | call to thread | thread.cpp:33:1:33:1 | t3 | | | thread.cpp:28:38:28:38 | s | thread.cpp:28:37:28:38 | & ... | | +| thread.cpp:30:18:32:8 | call to thread | thread.cpp:33:1:33:1 | t4 | | +| thread.cpp:30:24:30:24 | p | thread.cpp:30:24:30:24 | p | | +| thread.cpp:30:24:30:24 | p | thread.cpp:31:10:31:10 | p | | +| thread.cpp:32:7:32:7 | s | thread.cpp:32:6:32:7 | & ... | | | vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | | | vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | | | vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected index 9a128a360357..239ed2ec607d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected @@ -46936,6 +46936,8 @@ getParameterTypeName | stl.h:690:12:690:17 | thread | 0 | func:0 && | | stl.h:690:12:690:17 | thread | 0 | func:0 && | | stl.h:690:12:690:17 | thread | 0 | func:0 && | +| stl.h:690:12:690:17 | thread | 0 | func:0 && | +| stl.h:690:12:690:17 | thread | 1 | func:1 && | | stl.h:690:12:690:17 | thread | 1 | func:1 && | | stl.h:690:12:690:17 | thread | 1 | func:1 && | | stl.h:690:12:690:17 | thread | 1 | func:1 && | @@ -47196,6 +47198,11 @@ getParameterTypeName | thread.cpp:14:6:14:22 | thread_function_2 | 0 | S | | thread.cpp:18:6:18:22 | thread_function_3 | 0 | S * | | thread.cpp:18:6:18:22 | thread_function_3 | 1 | int | +| thread.cpp:30:18:30:18 | (unnamed constructor) | 0 | const lambda [] type at line 762, col. 18 & | +| thread.cpp:30:18:30:18 | (unnamed constructor) | 0 | lambda [] type at line 762, col. 18 && | +| thread.cpp:30:18:30:18 | operator= | 0 | const lambda [] type at line 762, col. 18 & | +| thread.cpp:30:20:30:20 | _FUN | 0 | S * | +| thread.cpp:30:20:30:20 | operator() | 0 | S * | | vector.cpp:13:6:13:9 | sink | 0 | int | | vector.cpp:14:27:14:30 | sink | 0 | vector> & | | vector.cpp:14:27:14:30 | sink | 0 | vector> & | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp index b0393801a94c..5a39669d1c6e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp @@ -26,4 +26,8 @@ void test_thread() { std::thread t1(thread_function_1, &s); std::thread t2(thread_function_2, s); std::thread t3(thread_function_3, &s, 42); + + std::thread t4([](S* p) { + sink(p->x); // $ ir + }, &s); } \ No newline at end of file








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/github/codeql/pull/20023.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy