@@ -2,7 +2,7 @@ private import codeql.util.Unit
22private import rust
33private import rust as R
44private import codeql.rust.dataflow.DataFlow
5- private import codeql.rust.dataflow.internal.DataFlowImpl
5+ private import codeql.rust.dataflow.internal.DataFlowImpl as DataFlowImpl
66private import codeql.rust.dataflow.internal.Node as Node
77private import codeql.rust.dataflow.internal.Content
88private import codeql.rust.dataflow.FlowSource as FlowSource
@@ -11,7 +11,25 @@ private import codeql.rust.dataflow.internal.TaintTrackingImpl
1111private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
1212private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
1313
14- module ModelGeneratorInput implements ModelGeneratorInputSig< Location , RustDataFlow > {
14+ private predicate relevant ( Function api ) {
15+ // Only include functions that have a resolved path.
16+ api .hasCrateOrigin ( ) and
17+ api .hasExtendedCanonicalPath ( ) and
18+ (
19+ // This excludes closures (these are not exported API endpoints) and
20+ // functions without a `pub` visiblity. A function can be `pub` without
21+ // ultimately being exported by a crate, so this is an overapproximation.
22+ api .hasVisibility ( )
23+ or
24+ // If a method implements a public trait it is exposed through the trait.
25+ // We overapproximate this by including all trait method implementations.
26+ exists ( Impl impl | impl .hasTrait ( ) and impl .getAssocItemList ( ) .getAssocItem ( _) = api )
27+ )
28+ }
29+
30+ module ModelGeneratorCommonInput implements
31+ ModelGeneratorCommonInputSig< Location , DataFlowImpl:: RustDataFlow >
32+ {
1533 // NOTE: We are not using type information for now.
1634 class Type = Unit ;
1735
@@ -23,55 +41,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
2341 Type getType ( ) { any ( ) }
2442 }
2543
26- Callable getAsExprEnclosingCallable ( NodeExtended node ) { result = node .asExpr ( ) .getScope ( ) }
27-
2844 Callable getEnclosingCallable ( NodeExtended node ) {
2945 result = node .( Node:: Node ) .getEnclosingCallable ( ) .asCfgScope ( )
3046 }
3147
32- Parameter asParameter ( NodeExtended node ) { result = node .asParameter ( ) }
33-
34- private predicate relevant ( Function api ) {
35- // Only include functions that have a resolved path.
36- api .hasCrateOrigin ( ) and
37- api .hasExtendedCanonicalPath ( ) and
38- (
39- // This excludes closures (these are not exported API endpoints) and
40- // functions without a `pub` visiblity. A function can be `pub` without
41- // ultimately being exported by a crate, so this is an overapproximation.
42- api .hasVisibility ( )
43- or
44- // If a method implements a public trait it is exposed through the trait.
45- // We overapproximate this by including all trait method implementations.
46- exists ( Impl impl | impl .hasTrait ( ) and impl .getAssocItemList ( ) .getAssocItem ( _) = api )
47- )
48- }
49-
50- predicate isUninterestingForDataFlowModels ( Callable api ) { none ( ) }
51-
52- predicate isUninterestingForHeuristicDataFlowModels ( Callable api ) { none ( ) }
53-
54- class SourceOrSinkTargetApi extends Callable {
55- SourceOrSinkTargetApi ( ) { relevant ( this ) }
56- }
57-
58- class SinkTargetApi extends SourceOrSinkTargetApi { }
59-
60- class SourceTargetApi extends SourceOrSinkTargetApi { }
61-
62- class SummaryTargetApi extends Callable {
63- private Callable lift ;
64-
65- SummaryTargetApi ( ) {
66- lift = this and
67- relevant ( this )
68- }
69-
70- Callable lift ( ) { result = lift }
71-
72- predicate isRelevant ( ) { relevant ( this ) }
73- }
74-
7548 predicate isRelevantType ( Type t ) { any ( ) }
7649
7750 /**
@@ -82,7 +55,9 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
8255 string qualifierString ( ) { result = "Argument[self]" }
8356
8457 string parameterAccess ( R:: ParamBase p ) {
85- result = "Argument[" + any ( ParameterPosition pos | p = pos .getParameterIn ( _) ) .toString ( ) + "]"
58+ result =
59+ "Argument[" + any ( DataFlowImpl:: ParameterPosition pos | p = pos .getParameterIn ( _) ) .toString ( ) +
60+ "]"
8661 }
8762
8863 string parameterContentAccess ( R:: ParamBase p ) { result = parameterAccess ( p ) }
@@ -92,12 +67,12 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
9267 }
9368
9469 bindingset [ c]
95- string paramReturnNodeAsOutput ( Callable c , ParameterPosition pos ) {
70+ string paramReturnNodeAsOutput ( Callable c , DataFlowImpl :: ParameterPosition pos ) {
9671 result = paramReturnNodeAsContentOutput ( c , pos )
9772 }
9873
9974 bindingset [ c]
100- string paramReturnNodeAsContentOutput ( Callable c , ParameterPosition pos ) {
75+ string paramReturnNodeAsContentOutput ( Callable c , DataFlowImpl :: ParameterPosition pos ) {
10176 result = parameterContentAccess ( c .getParamList ( ) .getParam ( pos .getPosition ( ) ) )
10277 or
10378 pos .isSelf ( ) and result = qualifierString ( )
@@ -107,40 +82,51 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
10782 result = ret .( Node:: Node ) .getEnclosingCallable ( ) .asCfgScope ( )
10883 }
10984
110- predicate isOwnInstanceAccessNode ( RustDataFlow:: ReturnNode node ) {
85+ predicate isOwnInstanceAccessNode ( DataFlowImpl :: RustDataFlow:: ReturnNode node ) {
11186 // This is probably not relevant to implement for Rust, as we only use
11287 // `captureMixedFlow` which doesn't explicitly distinguish between
11388 // functions that return `self` and those that don't.
11489 none ( )
11590 }
11691
117- predicate sinkModelSanitizer ( DataFlow:: Node node ) { none ( ) }
92+ predicate containerContent ( DataFlow:: ContentSet c ) {
93+ c .( SingletonContentSet ) .getContent ( ) instanceof ElementContent
94+ }
11895
119- /**
120- * Holds if `source` is an API entrypoint, i.e., a source of input where data
121- * can flow in to a library. This is used for creating sink models, as we
122- * only want to mark functions as sinks if input to the function can reach
123- * (from an input source) a known sink.
124- */
125- predicate apiSource ( DataFlow:: Node source ) { source instanceof DataFlow:: ParameterNode }
96+ string partialModelRow ( Callable api , int i ) {
97+ i = 0 and result = api .( Function ) .getCrateOrigin ( ) // crate
98+ or
99+ i = 1 and result = api .( Function ) .getExtendedCanonicalPath ( ) // name
100+ }
126101
127- bindingset [ sourceEnclosing , api]
128- predicate irrelevantSourceSinkApi ( Callable sourceEnclosing , SourceTargetApi api ) { none ( ) }
102+ string partialNeutralModelRow ( Callable api , int i ) { result = partialModelRow ( api , i ) }
103+ }
129104
130- string getInputArgument ( DataFlow:: Node source ) {
131- result = "Argument[" + source .( Node:: SourceParameterNode ) .getPosition ( ) .toString ( ) + "]"
132- }
105+ private import ModelGeneratorCommonInput
106+ private import MakeModelGeneratorFactory< Location , DataFlowImpl:: RustDataFlow , RustTaintTracking , ModelGeneratorCommonInput >
133107
134- bindingset [ kind]
135- predicate isRelevantSinkKind ( string kind ) { any ( ) }
108+ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
109+ class SummaryTargetApi extends Callable {
110+ private Callable lift ;
136111
137- bindingset [ kind]
138- predicate isRelevantSourceKind ( string kind ) { any ( ) }
112+ SummaryTargetApi ( ) {
113+ lift = this and
114+ relevant ( this )
115+ }
139116
140- predicate containerContent ( DataFlow:: ContentSet c ) {
141- c .( SingletonContentSet ) .getContent ( ) instanceof ElementContent
117+ Callable lift ( ) { result = lift }
118+
119+ predicate isRelevant ( ) { relevant ( this ) }
142120 }
143121
122+ Callable getAsExprEnclosingCallable ( NodeExtended node ) { result = node .asExpr ( ) .getScope ( ) }
123+
124+ Parameter asParameter ( NodeExtended node ) { result = node .asParameter ( ) }
125+
126+ predicate isUninterestingForDataFlowModels ( Callable api ) { none ( ) }
127+
128+ predicate isUninterestingForHeuristicDataFlowModels ( Callable api ) { none ( ) }
129+
144130 predicate isAdditionalContentFlowStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) { none ( ) }
145131
146132 predicate isField ( DataFlow:: ContentSet c ) {
@@ -159,7 +145,7 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
159145 private string encodeContent ( ContentSet cs , string arg ) {
160146 result = FlowSummary:: Input:: encodeContent ( cs , arg )
161147 or
162- exists ( Content c | cs = TSingletonContentSet ( c ) |
148+ exists ( Content c | cs = DataFlowImpl :: TSingletonContentSet ( c ) |
163149 exists ( int pos |
164150 pos = c .( FunctionCallArgumentContent ) .getPosition ( ) and
165151 result = "Parameter" and
@@ -176,18 +162,47 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
176162 if arg = "" then result = name else result = name + "[" + arg + "]"
177163 )
178164 }
165+ }
179166
180- string partialModelRow ( Callable api , int i ) {
181- i = 0 and result = api .( Function ) .getCrateOrigin ( ) // crate
182- or
183- i = 1 and result = api .( Function ) .getExtendedCanonicalPath ( ) // name
167+ private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig {
168+ class SourceTargetApi extends Callable {
169+ SourceTargetApi ( ) { relevant ( this ) }
184170 }
185171
186- string partialNeutralModelRow ( Callable api , int i ) { result = partialModelRow ( api , i ) }
172+ bindingset [ sourceEnclosing, api]
173+ predicate irrelevantSourceSinkApi ( Callable sourceEnclosing , SourceTargetApi api ) { none ( ) }
174+
175+ bindingset [ kind]
176+ predicate isRelevantSourceKind ( string kind ) { any ( ) }
187177
188178 predicate sourceNode ( DataFlow:: Node node , string kind ) { FlowSource:: sourceNode ( node , kind ) }
179+ }
180+
181+ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
182+ class SinkTargetApi extends Callable {
183+ SinkTargetApi ( ) { relevant ( this ) }
184+ }
185+
186+ predicate sinkModelSanitizer ( DataFlow:: Node node ) { none ( ) }
187+
188+ /**
189+ * Holds if `source` is an API entrypoint, i.e., a source of input where data
190+ * can flow in to a library. This is used for creating sink models, as we
191+ * only want to mark functions as sinks if input to the function can reach
192+ * (from an input source) a known sink.
193+ */
194+ predicate apiSource ( DataFlow:: Node source ) { source instanceof DataFlow:: ParameterNode }
195+
196+ string getInputArgument ( DataFlow:: Node source ) {
197+ result = "Argument[" + source .( Node:: SourceParameterNode ) .getPosition ( ) .toString ( ) + "]"
198+ }
199+
200+ bindingset [ kind]
201+ predicate isRelevantSinkKind ( string kind ) { any ( ) }
189202
190203 predicate sinkNode ( DataFlow:: Node node , string kind ) { FlowSink:: sinkNode ( node , kind ) }
191204}
192205
193- import MakeModelGenerator< Location , RustDataFlow , RustTaintTracking , ModelGeneratorInput >
206+ import MakeSummaryModelGenerator< SummaryModelGeneratorInput > as SummaryModels
207+ import MakeSourceModelGenerator< SourceModelGeneratorInput > as SourceModels
208+ import MakeSinkModelGenerator< SinkModelGeneratorInput > as SinkModels
0 commit comments