@@ -7,6 +7,9 @@ private import Node as Node
77private import Content
88private import FlowSummaryImpl as FlowSummaryImpl
99private import codeql.rust.internal.CachedStages
10+ private import codeql.rust.internal.TypeInference as TypeInference
11+ private import codeql.rust.internal.Type as Type
12+ private import codeql.rust.frameworks.stdlib.Builtins as Builtins
1013
1114module RustTaintTracking implements InputSig< Location , RustDataFlow > {
1215 predicate defaultTaintSanitizer ( DataFlow:: Node node ) { none ( ) }
@@ -28,11 +31,22 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
2831 succ .asExpr ( ) = index
2932 )
3033 or
31- // Although data flow through collections and references is modeled using
32- // stores/reads, we also allow taint to flow out of a tainted collection
33- // or reference.
34- // This is needed in order to support taint-tracking configurations where
35- // the source is a collection or reference.
34+ // Read steps give rise to taint steps. This has the effect that if `foo`
35+ // is tainted and an operation reads from `foo` (e.g., `foo.bar`) then
36+ // taint is propagated. We limit this to not apply if the type of the
37+ // operation is a small primitive type as these are often uninteresting
38+ // (for instance in the case of an injection query).
39+ RustDataFlow:: readContentStep ( pred , _, succ ) and
40+ not exists ( Struct s |
41+ s = TypeInference:: inferType ( succ .asExpr ( ) ) .( Type:: StructType ) .getStruct ( )
42+ |
43+ s instanceof Builtins:: NumericType or
44+ s instanceof Builtins:: Bool or
45+ s instanceof Builtins:: Char
46+ )
47+ or
48+ // Let all read steps (including those from flow summaries and those that
49+ // result in small primitive types) give rise to taint steps.
3650 exists ( SingletonContentSet cs | RustDataFlow:: readStep ( pred , cs , succ ) |
3751 cs .getContent ( ) instanceof ElementContent
3852 or
0 commit comments