@@ -29,6 +29,12 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> Lang> {
2929 */
3030 bindingset [ node]
3131 predicate defaultImplicitTaintRead ( Lang:: Node node , Lang:: ContentSet c ) ;
32+
33+ /**
34+ * Holds if the additional step from `src` to `sink` should be considered in
35+ * speculative taint flow exploration.
36+ */
37+ predicate speculativeTaintStep ( Lang:: Node src , Lang:: Node sink ) ;
3238}
3339
3440/**
@@ -130,4 +136,124 @@ module TaintFlowMake<
130136 {
131137 import GlobalWithState< Config >
132138 }
139+
140+ signature int speculationLimitSig ( ) ;
141+
142+ private module AddSpeculativeTaintSteps<
143+ DataFlowInternal:: FullStateConfigSig Config, speculationLimitSig / 0 speculationLimit> implements
144+ DataFlowInternal:: FullStateConfigSig
145+ {
146+ import Config
147+
148+ private predicate relevantState ( Config:: FlowState state ) {
149+ Config:: isSource ( _, state )
150+ or
151+ exists ( Config:: FlowState state0 |
152+ relevantState ( state0 ) and Config:: isAdditionalFlowStep ( _, state0 , _, state , _)
153+ )
154+ }
155+
156+ private newtype TFlowState =
157+ TMkFlowState ( Config:: FlowState state , int spec ) {
158+ relevantState ( state ) and spec = [ 0 .. speculationLimit ( ) ]
159+ }
160+
161+ class FlowState extends TFlowState {
162+ private Config:: FlowState state ;
163+ private int spec ;
164+
165+ FlowState ( ) { this = TMkFlowState ( state , spec ) }
166+
167+ string toString ( ) { result = "FlowState" }
168+
169+ Config:: FlowState getState ( ) { result = state }
170+
171+ int getSpec ( ) { result = spec }
172+ }
173+
174+ predicate isSource ( DataFlowLang:: Node source , FlowState state ) {
175+ Config:: isSource ( source , state .getState ( ) ) and state .getSpec ( ) = 0
176+ }
177+
178+ predicate isSink ( DataFlowLang:: Node sink , FlowState state ) {
179+ Config:: isSink ( sink , state .getState ( ) )
180+ }
181+
182+ predicate isBarrier ( DataFlowLang:: Node node , FlowState state ) {
183+ Config:: isBarrier ( node , state .getState ( ) )
184+ }
185+
186+ predicate isBarrierIn ( DataFlowLang:: Node node , FlowState state ) {
187+ Config:: isBarrierIn ( node , state .getState ( ) )
188+ }
189+
190+ predicate isBarrierOut ( DataFlowLang:: Node node , FlowState state ) {
191+ Config:: isBarrierOut ( node , state .getState ( ) )
192+ }
193+
194+ predicate isAdditionalFlowStep (
195+ DataFlowLang:: Node node1 , FlowState state1 , DataFlowLang:: Node node2 , FlowState state2 ,
196+ string model
197+ ) {
198+ Config:: isAdditionalFlowStep ( node1 , state1 .getState ( ) , node2 , state2 .getState ( ) , model ) and
199+ state1 .getSpec ( ) = state2 .getSpec ( )
200+ or
201+ speculativeTaintStep ( node1 , node2 ) and
202+ not defaultAdditionalTaintStep ( node1 , node2 , _) and
203+ not Config:: isAdditionalFlowStep ( node1 , _, node2 , _, _) and
204+ not Config:: isAdditionalFlowStep ( node1 , node2 , _) and
205+ model = "Speculative" and
206+ state1 .getSpec ( ) + 1 = state2 .getSpec ( ) and
207+ state1 .getState ( ) = state2 .getState ( )
208+ }
209+ }
210+
211+ module SpeculativeFlow< DataFlow:: ConfigSig Config, speculationLimitSig / 0 speculationLimit>
212+ implements DataFlow:: GlobalFlowSig
213+ {
214+ private module Config0 implements DataFlowInternal:: FullStateConfigSig {
215+ import DataFlowInternal:: DefaultState< Config >
216+ import Config
217+
218+ predicate isAdditionalFlowStep (
219+ DataFlowLang:: Node node1 , DataFlowLang:: Node node2 , string model
220+ ) {
221+ Config:: isAdditionalFlowStep ( node1 , node2 ) and model = "Config"
222+ }
223+ }
224+
225+ private module C implements DataFlowInternal:: FullStateConfigSig {
226+ import AddTaintDefaults< AddSpeculativeTaintSteps< Config0 , speculationLimit / 0 > >
227+ }
228+
229+ import DataFlowInternal:: Impl< C >
230+ }
231+
232+ module SpeculativeFlowWithState<
233+ DataFlow:: StateConfigSig Config, speculationLimitSig / 0 speculationLimit> implements
234+ DataFlow:: GlobalFlowSig
235+ {
236+ private module Config0 implements DataFlowInternal:: FullStateConfigSig {
237+ import Config
238+
239+ predicate isAdditionalFlowStep (
240+ DataFlowLang:: Node node1 , DataFlowLang:: Node node2 , string model
241+ ) {
242+ Config:: isAdditionalFlowStep ( node1 , node2 ) and model = "Config"
243+ }
244+
245+ predicate isAdditionalFlowStep (
246+ DataFlowLang:: Node node1 , FlowState state1 , DataFlowLang:: Node node2 , FlowState state2 ,
247+ string model
248+ ) {
249+ Config:: isAdditionalFlowStep ( node1 , state1 , node2 , state2 ) and model = "Config"
250+ }
251+ }
252+
253+ private module C implements DataFlowInternal:: FullStateConfigSig {
254+ import AddTaintDefaults< AddSpeculativeTaintSteps< Config0 , speculationLimit / 0 > >
255+ }
256+
257+ import DataFlowInternal:: Impl< C >
258+ }
133259}
0 commit comments