@@ -593,6 +593,89 @@ private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode
593593 }
594594}
595595
596+ private Type stripReferences ( Type type ) {
597+ exists ( Type unspecifiedType | unspecifiedType = type .getUnspecifiedType ( ) |
598+ result = unspecifiedType .( Cpp:: ReferenceType ) .getBaseType ( ) .getUnspecifiedType ( )
599+ or
600+ not unspecifiedType instanceof Cpp:: ReferenceType and
601+ result = unspecifiedType
602+ )
603+ }
604+
605+ private predicate forwardingCallTargetsConstructor (
606+ CallInstruction call , Cpp:: Constructor constructor
607+ ) {
608+ exists ( int start |
609+ External:: forwards ( call .getStaticCallTarget ( ) , constructor , start ) and
610+ call .getNumberOfPositionalArguments ( ) = start + constructor .getNumberOfParameters ( ) and
611+ forall ( int i , Type typeCall , Type typeConstructor |
612+ i = [ 0 .. constructor .getNumberOfParameters ( ) - 1 ] and
613+ typeCall = stripReferences ( call .getPositionalArgument ( start + i ) .getResultType ( ) ) and
614+ typeConstructor = stripReferences ( constructor .getParameter ( i ) .getUnspecifiedType ( ) )
615+ |
616+ typeCall = typeConstructor
617+ )
618+ )
619+ }
620+
621+ /** Holds if `call` is a call that forwards arguments to a constructor call. */
622+ predicate isForwarderConstructorArgumentNodeImpl ( CallInstruction call ) {
623+ forwardingCallTargetsConstructor ( call , _)
624+ }
625+
626+ /**
627+ * In order to implement a MaD summary for a flow such as:
628+ * ```
629+ * struct Foo {
630+ * int x;
631+ * Foo(int x) { // (2)
632+ * this->x = x;
633+ * }
634+ * }
635+ *
636+ * std::vector<Foo> v;
637+ * int x = source();
638+ * v.emplace_back(x); // (1)
639+ * sink(v.back());
640+ * ```
641+ * we model it as if the code was:
642+ * ```
643+ * v.__emplace_back(x, &Foo)
644+ * ```
645+ * (nevermind that this is not real C++ since you cannot take the address of a
646+ * constructor.)
647+ * where `__emplace_back` invokes `Foo` with the `x` argument and returns the
648+ * result.
649+ *
650+ * This class serves as the argument node for `&Foo`.
651+ */
652+ private class ForwarderConstructorArgumentNode extends ArgumentNode ,
653+ TForwarderConstructorArgumentNode
654+ {
655+ private CallInstruction call ;
656+
657+ ForwarderConstructorArgumentNode ( ) { this = TForwarderConstructorArgumentNode ( call ) }
658+
659+ override predicate sourceArgumentOf ( CallInstruction c , ArgumentPosition pos ) {
660+ c = call and pos = TForwardPosition ( )
661+ }
662+
663+ /**
664+ * Gets a constructor which may be targeted by this forwarding call.
665+ */
666+ Cpp:: Constructor getAConstructor ( ) { forwardingCallTargetsConstructor ( call , result ) }
667+
668+ override DataFlowCallable getEnclosingCallable ( ) {
669+ result .asSourceCallable ( ) = this .getFunction ( )
670+ }
671+
672+ override Declaration getFunction ( ) { result = call .getEnclosingFunction ( ) }
673+
674+ override Location getLocationImpl ( ) { result = call .getLocation ( ) }
675+
676+ override string toStringImpl ( ) { result = "forwarder for " + call .toString ( ) }
677+ }
678+
596679/**
597680 * An argument node that is part of a summary. These only occur when the
598681 * summary contains a synthesized call.
@@ -1275,6 +1358,19 @@ private predicate summarizedCallableIsManual(SummarizedCallable sc) {
12751358 sc .asSummarizedCallable ( ) .hasManualModel ( )
12761359}
12771360
1361+ private DataFlowCallable getTarget ( Declaration target ) {
1362+ // Don't use the source callable if there is a manual model for the target.
1363+ not exists ( SummarizedCallable sc |
1364+ sc .asSummarizedCallable ( ) = target and
1365+ summarizedCallableIsManual ( sc )
1366+ ) and
1367+ result .asSourceCallable ( ) = target
1368+ or
1369+ // When there is no function body, or when we have a manual model, dispatch to the summary.
1370+ ( not target .hasDefinition ( ) or summarizedCallableIsManual ( result ) ) and
1371+ result .asSummarizedCallable ( ) = target
1372+ }
1373+
12781374/**
12791375 * A function call relevant for data flow. This includes calls from source
12801376 * code and calls inside library callables with a flow summary.
@@ -1310,20 +1406,7 @@ class DataFlowCall extends TDataFlowCall {
13101406 * whether is it manual or generated.
13111407 */
13121408 final DataFlowCallable getStaticCallTarget ( ) {
1313- exists ( Declaration target | target = this .getStaticCallSourceTarget ( ) |
1314- // Don't use the source callable if there is a manual model for the
1315- // target
1316- not exists ( SummarizedCallable sc |
1317- sc .asSummarizedCallable ( ) = target and
1318- summarizedCallableIsManual ( sc )
1319- ) and
1320- result .asSourceCallable ( ) = target
1321- or
1322- // When there is no function body, or when we have a manual model then
1323- // we dispatch to the summary.
1324- ( not target .hasDefinition ( ) or summarizedCallableIsManual ( result ) ) and
1325- result .asSummarizedCallable ( ) = target
1326- )
1409+ result = getTarget ( this .getStaticCallSourceTarget ( ) )
13271410 }
13281411
13291412 /**
@@ -1510,6 +1593,8 @@ predicate nodeIsHidden(Node n) {
15101593 n instanceof SsaSynthNode
15111594 or
15121595 n .( FlowSummaryNode ) .getSummaryNode ( ) .isHidden ( )
1596+ or
1597+ n instanceof ForwarderConstructorArgumentNode
15131598}
15141599
15151600predicate neverSkipInPathGraph ( Node n ) {
@@ -1591,6 +1676,9 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
15911676 kind .isFunctionPointer ( ) and
15921677 creation .asInstruction ( ) .( FunctionAddressInstruction ) .getFunctionSymbol ( ) = c .asSourceCallable ( )
15931678 or
1679+ kind .isFunctionPointer ( ) and
1680+ c = getTarget ( creation .( ForwarderConstructorArgumentNode ) .getAConstructor ( ) )
1681+ or
15941682 kind .isFunctor ( ) and
15951683 exists ( OperatorCall operator | operator = c .asSourceCallable ( ) |
15961684 isFunctorCreationWithoutConstructor ( creation , operator )
0 commit comments