@@ -54,68 +54,33 @@ module AccessAfterLifetimeConfig implements DataFlow::ConfigSig {
5454
5555module AccessAfterLifetimeFlow = TaintTracking:: Global< AccessAfterLifetimeConfig > ;
5656
57- private newtype TTcNode =
58- TSource ( Source s , Variable target ) {
59- AccessAfterLifetimeFlow:: flow ( s , _) and sourceValueScope ( s , target , _)
60- } or
61- TBlockExpr ( BlockExpr be ) or
62- TSink ( Sink s ) { AccessAfterLifetimeFlow:: flow ( _, s ) }
63-
64- private class TcNode extends TTcNode {
65- Source asSource ( Variable target ) { this = TSource ( result , target ) }
66-
67- BlockExpr asBlockExpr ( ) { this = TBlockExpr ( result ) }
68-
69- Sink asSink ( ) { this = TSink ( result ) }
70-
71- string toString ( ) {
72- result = this .asSource ( _) .toString ( )
73- or
74- result = this .asBlockExpr ( ) .toString ( )
75- or
76- result = this .asSink ( ) .toString ( )
77- }
78-
79- Location getLocation ( ) {
80- result = this .asSource ( _) .getLocation ( )
81- or
82- result = this .asBlockExpr ( ) .getLocation ( )
83- or
84- result = this .asSink ( ) .getLocation ( )
85- }
57+ predicate sourceBlock ( Source s , Variable target , BlockExpr be ) {
58+ AccessAfterLifetimeFlow:: flow ( s , _) and
59+ sourceValueScope ( s , target , be .getEnclosingBlock * ( ) )
8660}
8761
88- pragma [ nomagic]
89- private predicate tcStep ( TcNode a , TcNode b ) {
90- // `b` is a child of `a`
91- exists ( Source source , Variable target , BlockExpr be |
92- source = a .asSource ( target ) and
93- be = b .asBlockExpr ( ) .getEnclosingBlock * ( ) and
94- sourceValueScope ( source , target , be ) and
95- AccessAfterLifetimeFlow:: flow ( source , _)
96- )
97- or
62+ predicate sinkBlock ( Sink s , BlockExpr be ) { be = s .asExpr ( ) .getEnclosingBlock ( ) }
63+
64+ private predicate tcStep ( BlockExpr a , BlockExpr b ) {
9865 // propagate through function calls
9966 exists ( Call call |
100- a . asBlockExpr ( ) = call .getEnclosingBlock ( ) and
101- call .getARuntimeTarget ( ) = b .asBlockExpr ( ) . getEnclosingCallable ( )
67+ a = call .getEnclosingBlock ( ) and
68+ call .getARuntimeTarget ( ) = b .getEnclosingCallable ( )
10269 )
103- or
104- a .asBlockExpr ( ) = b .asSink ( ) .asExpr ( ) .getEnclosingBlock ( )
10570}
10671
107- private predicate isTcSource ( TcNode n ) { n instanceof TSource }
72+ private predicate isTcSource ( BlockExpr be ) { sourceBlock ( _ , _ , be ) }
10873
109- private predicate isTcSink ( TcNode n ) { n instanceof TSink }
74+ private predicate isTcSink ( BlockExpr be ) { sinkBlock ( _ , be ) }
11075
11176/**
11277 * Holds if block `a` contains block `b`, in the sense that a stack allocated variable in
11378 * `a` may still be on the stack during execution of `b`. This is interprocedural,
11479 * but is an overapproximation that doesn't accurately track call contexts
115- * (for example if `f` and `g` both call `b`, then then depending on the
80+ * (for example if `f` and `g` both call `b`, then depending on the
11681 * caller a variable in `f` or `g` may or may-not be on the stack during `b`).
11782 */
118- private predicate mayEncloseOnStack ( TcNode a , TcNode b ) =
83+ private predicate mayEncloseOnStack ( BlockExpr a , BlockExpr b ) =
11984 doublyBoundedFastTC( tcStep / 2 , isTcSource / 1 , isTcSink / 1 ) ( a , b )
12085
12186/**
@@ -126,7 +91,14 @@ private predicate mayEncloseOnStack(TcNode a, TcNode b) =
12691predicate dereferenceAfterLifetime ( Source source , Sink sink , Variable target ) {
12792 AccessAfterLifetimeFlow:: flow ( source , sink ) and
12893 sourceValueScope ( source , target , _) and
129- not mayEncloseOnStack ( TSource ( source , target ) , TSink ( sink ) )
94+ not exists ( BlockExpr beSource , BlockExpr beSink |
95+ sourceBlock ( source , target , beSource ) and
96+ sinkBlock ( sink , beSink )
97+ |
98+ beSource = beSink
99+ or
100+ mayEncloseOnStack ( beSource , beSink )
101+ )
130102}
131103
132104from
0 commit comments