@@ -4,7 +4,11 @@ private import DataFlowUtil
44private import DataFlowImplCommon as DataFlowImplCommon
55private import semmle.code.cpp.models.interfaces.Allocation as Alloc
66private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
7+ private import semmle.code.cpp.models.interfaces.Taint as Taint
8+ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
9+ private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
710private import semmle.code.cpp.ir.internal.IRCppLanguage
11+ private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
812private import DataFlowPrivate
913private import ssa0.SsaInternals as SsaInternals0
1014import SsaInternalsCommon
@@ -138,12 +142,11 @@ private newtype TDefOrUseImpl =
138142 isIteratorUse ( container , iteratorAddress , _, indirectionIndex )
139143 } or
140144 TFinalParameterUse ( Parameter p , int indirectionIndex ) {
141- // Avoid creating parameter nodes if there is no definitions of the variable other than the initializaion.
142- exists ( SsaInternals0:: Def def |
143- def .getSourceVariable ( ) .getBaseVariable ( ) .( BaseIRVariable ) .getIRVariable ( ) .getAst ( ) = p and
144- not def .getValue ( ) .asInstruction ( ) instanceof InitializeParameterInstruction and
145- underlyingTypeIsModifiableAt ( p .getUnderlyingType ( ) , indirectionIndex )
146- )
145+ underlyingTypeIsModifiableAt ( p .getUnderlyingType ( ) , indirectionIndex ) and
146+ // Only create an SSA read for the final use of a parameter if there's
147+ // actually a body of the enclosing function. If there's no function body
148+ // then we'll never need to flow out of the function anyway.
149+ p .getFunction ( ) .hasDefinition ( )
147150 }
148151
149152private predicate isGlobalUse (
@@ -796,10 +799,58 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
796799 )
797800}
798801
802+ private predicate inOut ( FIO:: FunctionInput input , FIO:: FunctionOutput output ) {
803+ exists ( int indirectionIndex |
804+ input .isQualifierObject ( indirectionIndex ) and
805+ output .isQualifierObject ( indirectionIndex )
806+ or
807+ exists ( int i |
808+ input .isParameterDeref ( i , indirectionIndex ) and
809+ output .isParameterDeref ( i , indirectionIndex )
810+ )
811+ )
812+ }
813+
814+ /**
815+ * Holds if there should not be use-use flow out of `n`. That is, `n` is
816+ * an out-barrier to use-use flow. This includes:
817+ *
818+ * - an input to a call that would be assumed to have use-use flow to the same
819+ * argument as an output, but this flow should be blocked because the
820+ * function is modeled with another flow to that output (for example the
821+ * first argument of `strcpy`).
822+ * - a conversion that flows to such an input.
823+ */
824+ private predicate modeledFlowBarrier ( Node n ) {
825+ exists (
826+ FIO:: FunctionInput input , FIO:: FunctionOutput output , CallInstruction call ,
827+ PartialFlow:: PartialFlowFunction partialFlowFunc
828+ |
829+ n = callInput ( call , input ) and
830+ inOut ( input , output ) and
831+ exists ( callOutput ( call , output ) ) and
832+ partialFlowFunc = call .getStaticCallTarget ( ) and
833+ not partialFlowFunc .isPartialWrite ( output )
834+ |
835+ call .getStaticCallTarget ( ) .( DataFlow:: DataFlowFunction ) .hasDataFlow ( _, output )
836+ or
837+ call .getStaticCallTarget ( ) .( Taint:: TaintFunction ) .hasTaintFlow ( _, output )
838+ )
839+ or
840+ exists ( Operand operand , Instruction instr , Node n0 , int indirectionIndex |
841+ modeledFlowBarrier ( n0 ) and
842+ nodeHasInstruction ( n0 , instr , indirectionIndex ) and
843+ conversionFlow ( operand , instr , false , _) and
844+ nodeHasOperand ( n , operand , indirectionIndex )
845+ )
846+ }
847+
799848/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
800849predicate ssaFlow ( Node nodeFrom , Node nodeTo ) {
801850 exists ( Node nFrom , boolean uncertain , SsaDefOrUse defOrUse |
802- ssaFlowImpl ( defOrUse , nFrom , nodeTo , uncertain ) and nodeFrom != nodeTo
851+ ssaFlowImpl ( defOrUse , nFrom , nodeTo , uncertain ) and
852+ not modeledFlowBarrier ( nFrom ) and
853+ nodeFrom != nodeTo
803854 |
804855 if uncertain = true then nodeFrom = [ nFrom , getAPriorDefinition ( defOrUse ) ] else nodeFrom = nFrom
805856 )
0 commit comments