@@ -17,11 +17,9 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
1717
1818 class SummarizedCallableBase = Function ;
1919
20- class SourceBase extends Void {
21- Location getLocation ( ) { none ( ) }
22- }
20+ class SourceBase = Function ;
2321
24- class SinkBase = SourceBase ;
22+ class SinkBase = Function ;
2523
2624 class FlowSummaryCallBase = CallInstruction ;
2725
@@ -134,15 +132,192 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
134132
135133private import Make< Location , DataFlowImplSpecific:: CppDataFlow , Input > as Impl
136134
135+ private class ConversionCall extends Call {
136+ ConversionCall ( ) { this .getTarget ( ) instanceof ConversionOperator }
137+ }
138+
137139private module Input2 implements Impl:: Private:: InputSig2 {
138140 private import codeql.util.Void
139141
140- class SourceSinkReportingElement extends Void {
141- Location getLocation ( ) { none ( ) }
142+ pragma [ nomagic]
143+ private predicate hasFunctionAndIndirectionIndex (
144+ Function f , int indirectionIndex , Ssa:: ExplicitDefinition def
145+ ) {
146+ def .getFunction ( ) = f and
147+ def .getSourceVariable ( ) .getIRVariable ( ) instanceof IRReturnVariable and
148+ def .getIndirectionIndex ( ) = indirectionIndex
149+ }
150+
151+ /** Holds if `def` defines `e` as a returned value with return kind `rk`. */
152+ bindingset [ rk, e]
153+ private predicate isReturnExpr ( Function f , ReturnKind rk , Expr e ) {
154+ exists ( Ssa:: ExplicitDefinition def |
155+ hasFunctionAndIndirectionIndex ( f , rk .getIndirectionIndex ( ) , def ) and
156+ e =
157+ def .getAssignedInstruction ( )
158+ .( StoreInstruction )
159+ .getSourceValue ( )
160+ .getUnconvertedResultExpression ( )
161+ )
162+ }
163+
164+ private MemberFunction getFunctionFromType ( Expr e ) {
165+ result .getClassAndName ( "operator()" ) .getADerivedClass * ( ) = e .getUnspecifiedType ( )
166+ }
167+
168+ private Function getFunctionFromExpr ( Expr e ) {
169+ result = e .( FunctionAccess ) .getTarget ( )
170+ or
171+ result = e .( ConversionCall ) .getQualifier ( ) .( LambdaExpression ) .getLambdaFunction ( )
172+ }
173+
174+ class SourceSinkReportingElement extends Element {
175+ SourceSinkReportingElement ( ) { this instanceof Expr or this instanceof Parameter }
176+
177+ DataFlowCallable getEnclosingCallable ( ) {
178+ result .asSourceCallable ( ) =
179+ [ this .( Expr ) .getEnclosingFunction ( ) , this .( Parameter ) .getFunction ( ) ]
180+ }
181+
182+ /** Gets the function invoked when this element is used as a callback. */
183+ private Function getCallable ( ) {
184+ // The expression is a struct which implements `operator()`.
185+ result = getFunctionFromType ( this )
186+ or
187+ // The expression is a function pointer
188+ result = getFunctionFromExpr ( this )
189+ or
190+ // The expression is an SSA read of an assignment of a callable
191+ exists ( Ssa:: Definition def |
192+ def .getAUse ( ) .getDef ( ) .getUnconvertedResultExpression ( ) = this and
193+ result =
194+ getFunctionFromExpr ( def .getAnUltimateDefinition ( )
195+ .( Ssa:: DirectExplicitDefinition )
196+ .getAssignedInstruction ( )
197+ .( StoreInstruction )
198+ .getSourceValue ( )
199+ .getUnconvertedResultExpression ( ) )
200+ )
201+ }
202+
203+ SourceSinkReportingElement getASuccessor ( Impl:: Private:: SummaryComponent sc ) {
204+ exists ( Function f | f = this .getCallable ( ) |
205+ exists ( ParameterPosition pos | sc = Impl:: Private:: SummaryComponent:: parameter ( pos ) |
206+ result = pos .getParameter ( f )
207+ )
208+ or
209+ exists ( ReturnKind rk |
210+ sc = Impl:: Private:: SummaryComponent:: return ( rk ) and
211+ isReturnExpr ( f , rk , result )
212+ )
213+ )
214+ }
215+ }
216+
217+ bindingset [ source, sc]
218+ SourceSinkReportingElement getASourceReportingElement (
219+ Input:: SourceBase source , Impl:: Private:: SummaryComponent sc
220+ ) {
221+ exists ( Call call | call .getTarget ( ) = source |
222+ sc = Impl:: Private:: SummaryComponent:: return ( _) and
223+ result = call
224+ or
225+ exists ( ArgumentPosition pos |
226+ sc = Impl:: Private:: SummaryComponent:: argument ( pos ) and
227+ result = pos .getArgument ( call )
228+ )
229+ )
230+ or
231+ exists ( ParameterPosition pos |
232+ sc = Impl:: Private:: SummaryComponent:: parameter ( pos ) and
233+ result = pos .getParameter ( source )
234+ )
235+ }
236+
237+ pragma [ nomagic]
238+ private IndirectReturnOutNode getIndirectReturn ( CallInstruction call , NormalReturnKind rk ) {
239+ result .getCallInstruction ( ) = call and
240+ pragma [ only_bind_out ] ( result .getIndirectionIndex ( ) ) =
241+ pragma [ only_bind_out ] ( rk .getIndirectionIndex ( ) )
242+ }
243+
244+ pragma [ nomagic]
245+ private predicate hasKindAndEnclosingFunction ( Function f , ReturnKind rk , ReturnNode r ) {
246+ r .getEnclosingCallable ( ) .asSourceCallable ( ) = f and
247+ r .getKind ( ) = rk
248+ }
142249
143- DataFlowCallable getEnclosingCallable ( ) { none ( ) }
250+ pragma [ nomagic]
251+ private predicate hasParameterAndIndirectionIndex (
252+ Parameter p , int indirectionIndex , ParameterNode n
253+ ) {
254+ n .getParameter ( ) = p and
255+ n .getIndirectionIndex ( ) = indirectionIndex
256+ }
144257
145- SourceSinkReportingElement getASuccessor ( Impl:: Private:: SummaryComponent sc ) { none ( ) }
258+ bindingset [ e, sc]
259+ Node getSourceDataFlowNode ( SourceSinkReportingElement e , Impl:: Private:: SummaryComponent sc ) {
260+ exists ( DataFlowCall call |
261+ exists ( ArgumentPosition pos |
262+ sc = Impl:: Private:: SummaryComponent:: argument ( pos ) and
263+ pos .getArgument ( call .asCallInstruction ( ) .getUnconvertedResultExpression ( ) ) = e
264+ |
265+ pos .getIndirectionIndex ( ) = 0 and
266+ result .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = e
267+ or
268+ result .( PostUpdateNode ) .getPreUpdateNode ( ) .asIndirectExpr ( pos .getIndirectionIndex ( ) ) = e
269+ )
270+ or
271+ exists ( ReturnKind rk |
272+ sc = Impl:: Private:: SummaryComponent:: return ( rk ) and
273+ // When `e` is a call the node becomes an `OutNode`.
274+ e = call .asCallInstruction ( ) .getUnconvertedResultExpression ( )
275+ |
276+ rk .getIndirectionIndex ( ) = 0 and
277+ simpleOutNode ( result , call .asCallInstruction ( ) )
278+ or
279+ result = getIndirectReturn ( call .asCallInstruction ( ) , rk )
280+ )
281+ )
282+ or
283+ exists ( ParameterPosition pos |
284+ sc = Impl:: Private:: SummaryComponent:: parameter ( pos ) and
285+ hasParameterAndIndirectionIndex ( e , pos .getIndirectionIndex ( ) , result )
286+ )
287+ or
288+ exists ( Function f , ReturnKind rk |
289+ sc = Impl:: Private:: SummaryComponent:: return ( rk ) and
290+ // When `e` is the returned expression from a function the node is
291+ // the `ReturnNode`.
292+ isReturnExpr ( f , rk , e ) and
293+ hasKindAndEnclosingFunction ( f , rk , result )
294+ )
295+ }
296+
297+ bindingset [ sink, sc]
298+ SourceSinkReportingElement getASinkReportingElement (
299+ Input:: SinkBase sink , Impl:: Private:: SummaryComponent sc
300+ ) {
301+ exists ( Call call , ArgumentPosition pos |
302+ call .getTarget ( ) = sink and
303+ sc = Impl:: Private:: SummaryComponent:: argument ( pos ) and
304+ result = pos .getArgument ( call )
305+ )
306+ }
307+
308+ bindingset [ e, sc]
309+ Node getSinkDataFlowNode ( SourceSinkReportingElement e , Impl:: Private:: SummaryComponent sc ) {
310+ exists ( ArgumentPosition pos , CallInstruction call |
311+ sc = Impl:: Private:: SummaryComponent:: argument ( pos ) and
312+ pos .getArgument ( call .getUnconvertedResultExpression ( ) ) = e and
313+ result .( ArgumentNode ) .sourceArgumentOf ( call , pos )
314+ )
315+ or
316+ exists ( Function f , ReturnKind rk |
317+ sc = Impl:: Private:: SummaryComponent:: return ( rk ) and
318+ isReturnExpr ( f , rk , e ) and
319+ hasKindAndEnclosingFunction ( f , rk , result )
320+ )
146321 }
147322}
148323
@@ -319,3 +494,41 @@ module Private {
319494}
320495
321496module Public = Impl:: Public;
497+
498+ private class SourceModelFunction extends Public:: SourceElement instanceof Function {
499+ private string namespace ;
500+ private string type ;
501+ private boolean subtypes ;
502+ private string name ;
503+ private string signature ;
504+ private string ext ;
505+
506+ SourceModelFunction ( ) {
507+ sourceModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _) and
508+ this = interpretElement ( namespace , type , subtypes , name , signature , ext )
509+ }
510+
511+ override predicate isSource (
512+ string output , string kind , Public:: Provenance provenance , string model
513+ ) {
514+ sourceModel ( namespace , type , subtypes , name , signature , ext , output , kind , provenance , model )
515+ }
516+ }
517+
518+ private class SinkModelFunction extends Public:: SinkElement instanceof Function {
519+ private string namespace ;
520+ private string type ;
521+ private boolean subtypes ;
522+ private string name ;
523+ private string signature ;
524+ private string ext ;
525+
526+ SinkModelFunction ( ) {
527+ sinkModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _) and
528+ this = interpretElement ( namespace , type , subtypes , name , signature , ext )
529+ }
530+
531+ override predicate isSink ( string input , string kind , Public:: Provenance provenance , string model ) {
532+ sinkModel ( namespace , type , subtypes , name , signature , ext , input , kind , provenance , model )
533+ }
534+ }
0 commit comments