44 */
55
66import rust
7+ private import codeql.rust.elements.Call
78private import codeql.rust.dataflow.DataFlow
89private import codeql.rust.dataflow.FlowSource
910private import codeql.rust.dataflow.FlowSink
1011private import codeql.rust.Concepts
1112private import codeql.rust.dataflow.internal.Node
1213private import codeql.rust.security.Barriers as Barriers
14+ private import codeql.rust.internal.TypeInference as TypeInference
15+ private import codeql.rust.internal.Type
1316
1417/**
1518 * Provides default sources, sinks and barriers for detecting accesses to
@@ -47,11 +50,17 @@ module AccessInvalidPointer {
4750 ModelsAsDataSource ( ) { sourceNode ( this , "pointer-invalidate" ) }
4851 }
4952
50- /**
51- * A pointer access using the unary `*` operator.
52- */
53+ /** A raw pointer access using the unary `*` operator. */
5354 private class DereferenceSink extends Sink {
54- DereferenceSink ( ) { any ( DerefExpr p ) .getExpr ( ) = this .asExpr ( ) }
55+ DereferenceSink ( ) {
56+ exists ( Expr p , DerefExpr d | p = d .getExpr ( ) and p = this .asExpr ( ) |
57+ // Dereferencing a raw pointer is an unsafe operation. Hence relevant
58+ // dereferences must occur inside code marked as unsafe.
59+ // See: https://doc.rust-lang.org/reference/types/pointer.html#r-type.pointer.raw.safety
60+ ( p .getEnclosingBlock * ( ) .isUnsafe ( ) or p .getEnclosingCallable ( ) .( Function ) .isUnsafe ( ) ) and
61+ ( not exists ( TypeInference:: inferType ( p ) ) or TypeInference:: inferType ( p ) instanceof PtrType )
62+ )
63+ }
5564 }
5665
5766 /**
@@ -61,6 +70,40 @@ module AccessInvalidPointer {
6170 ModelsAsDataSink ( ) { sinkNode ( this , "pointer-access" ) }
6271 }
6372
73+ private class BarrierCall extends Barrier {
74+ BarrierCall ( ) {
75+ exists ( Call call , ArgumentPosition pos , string canonicalName |
76+ call .getStaticTarget ( ) .getCanonicalPath ( ) = canonicalName and
77+ this .asExpr ( ) = call .getArgument ( pos )
78+ |
79+ canonicalName = "<core::ptr::non_null::NonNull>::new" and pos .asPosition ( ) = 0
80+ )
81+ }
82+ }
83+
84+ private class NumericTypeBarrier extends Barrier instanceof Barriers:: NumericTypeBarrier { }
85+
86+ private class BooleanTypeBarrier extends Barrier instanceof Barriers:: BooleanTypeBarrier { }
87+
88+ private class FieldlessEnumTypeBarrier extends Barrier instanceof Barriers:: FieldlessEnumTypeBarrier
89+ { }
90+
91+ private class DefaultBarrier extends Barrier {
92+ DefaultBarrier ( ) {
93+ // A barrier for calls that statically resolve to the `Default::default`
94+ // trait function. Such calls are imprecise, and can always resolve to the
95+ // implementations for raw pointers that return a null pointer. This
96+ // creates many false positives in combination with other inaccuracies
97+ // (too many `pointer-access` sinks created by the model generator).
98+ //
99+ // We could try removing this barrier in the future when either 1/ the
100+ // model generator creates fewer spurious sinks or 2/ data flow for calls
101+ // to trait functions is more precise.
102+ this .asExpr ( ) .( Call ) .getStaticTarget ( ) .getCanonicalPath ( ) =
103+ "<_ as core::default::Default>::default"
104+ }
105+ }
106+
64107 /**
65108 * A barrier for invalid pointer access vulnerabilities for values checked to
66109 * be non-`null`.
0 commit comments