@@ -25,8 +25,7 @@ predicate parameterOf(Parameter p, Function f, int n) {
2525
2626/**
2727 * Holds if `instr` is the `n`'th argument to a call to the non-virtual function `f`, and
28- * `init` is the corresponding initiazation instruction that receives the value of
29- * `instr` in `f`.
28+ * `init` is the corresponding initiazation instruction that receives the value of `instr` in `f`.
3029 */
3130predicate flowIntoParameter (
3231 CallInstruction call , Instruction instr , Function f , int n , InitializeParameterInstruction init
@@ -39,9 +38,8 @@ predicate flowIntoParameter(
3938}
4039
4140/**
42- * Holds if `instr` is an argument to a call to the function `f`, and
43- * `init` is the corresponding initiazation instruction that receives the value of
44- * `instr` in `f`.
41+ * Holds if `instr` is an argument to a call to the function `f`, and `init` is the
42+ * corresponding initialization instruction that receives the value of `instr` in `f`.
4543 */
4644pragma [ noinline]
4745predicate getPositionalArgumentInitParam (
@@ -96,42 +94,32 @@ predicate isSource(InitializeParameterInstruction init, string msg, Class c) {
9694 init .getEnclosingFunction ( ) .getDeclaringType ( ) = c
9795}
9896
99- /**
100- * Holds if `instr` flows to the sink instruction `sink` that is a `this`
101- * pointer of type `sinkClass`
102- */
103- predicate flowsToSink ( Instruction instr , Instruction sink , Class sinkClass ) {
104- instr = sink and
105- isSink ( sink , _, sinkClass )
97+ /** Holds if `instr` flows to a sink. */
98+ predicate flowsToSink ( Instruction instr ) {
99+ isSink ( instr , _, _)
106100 or
107101 exists ( Instruction mid |
108- successor ( instr , mid , sinkClass ) and
109- flowsToSink ( mid , sink , sinkClass )
102+ successor ( instr , mid ) and
103+ flowsToSink ( mid )
110104 )
111105}
112106
113- /**
114- * Holds if `source` is an initialization of a `this` pointer of type `sourceClass`, and
115- * `source` flows to instruction `instr`.
116- */
117- predicate flowsFromSource ( Instruction source , Instruction instr , Class sourceClass ) {
118- source = instr and
119- isSource ( source , _, sourceClass )
107+ /** Holds if `instr` flows from a source. */
108+ predicate flowsFromSource ( Instruction instr ) {
109+ isSource ( instr , _, _)
120110 or
121111 exists ( Instruction mid |
122- successorFwd ( mid , instr , sourceClass ) and
123- flowsFromSource ( source , mid , sourceClass )
112+ successor ( mid , instr ) and
113+ flowsFromSource ( mid )
124114 )
125115}
126116
127117/**
128- * Holds if
129- * - `instr` is an argument (or argument indirection) to a call, and
130- * - `succ` is the corresponding initialization instruction in the call target, and
131- * - `succ` eventually flows to an instruction that is used as a `this` pointer of type `sinkClass`.
118+ * Holds if `instr` is an argument (or argument indirection) to a call, and
119+ * `succ` is the corresponding initialization instruction in the call target.
132120 */
133- predicate flowThroughCallable ( Instruction instr , Instruction succ , Class sinkClass ) {
134- flowsToSink ( succ , _ , sinkClass ) and
121+ predicate flowThroughCallable ( Instruction instr , Instruction succ ) {
122+ flowsToSink ( succ ) and
135123 (
136124 // Flow from an argument to a parameter
137125 exists ( CallInstruction call , InitializeParameterInstruction init | init = succ |
@@ -160,115 +148,57 @@ predicate flowThroughCallable(Instruction instr, Instruction succ, Class sinkCla
160148 )
161149}
162150
163- /**
164- * Holds if `instr` flows to `succ` and `succ` eventually flows to an instruction that is used
165- * as a `this` pointer of type `sinkClass`.
166- */
167- predicate successor ( Instruction instr , Instruction succ , Class sinkClass ) {
168- flowsToSink ( succ , _, sinkClass ) and
151+ /** Holds if `instr` flows to `succ`. */
152+ predicate successor ( Instruction instr , Instruction succ ) {
153+ flowsToSink ( succ ) and
169154 (
170155 irBbPostDominates ( succ .getBlock ( ) , instr .getBlock ( ) ) and
171156 (
172- (
173- succ .( CopyInstruction ) .getSourceValue ( ) = instr or
174- succ .( CheckedConvertOrNullInstruction ) .getUnary ( ) = instr or
175- succ .( ChiInstruction ) .getTotal ( ) = instr or
176- succ .( ConvertInstruction ) .getUnary ( ) = instr
177- )
178- or
157+ succ .( CopyInstruction ) .getSourceValue ( ) = instr or
158+ succ .( CheckedConvertOrNullInstruction ) .getUnary ( ) = instr or
159+ succ .( ChiInstruction ) .getTotal ( ) = instr or
160+ succ .( ConvertInstruction ) .getUnary ( ) = instr or
179161 succ .( InheritanceConversionInstruction ) .getUnary ( ) = instr
180162 )
181163 or
182- flowThroughCallable ( instr , succ , sinkClass )
164+ flowThroughCallable ( instr , succ )
183165 )
184166}
185167
186- /**
187- * Holds if
188- * - `instr` is an argument (or argument indirection) to a call, and
189- * - `succ` is the corresponding initialization instruction in the call target, and
190- * - there exists an initialization of a `this` pointer of type `sourceClass` that flows to `instr`.
191- */
192- predicate flowThroughCallableFwd ( Instruction instr , Instruction succ , Class sourceClass ) {
193- flowsFromSource ( _, instr , sourceClass ) and
194- (
195- // Flow from an argument to a parameter
196- exists ( CallInstruction call , InitializeParameterInstruction init | init = succ |
197- getPositionalArgumentInitParam ( call , instr , init , call .getStaticCallTarget ( ) )
198- or
199- getThisArgumentInitParam ( call , instr , init , call .getStaticCallTarget ( ) )
200- )
201- or
202- // Flow from argument indirection to parameter indirection
203- exists (
204- CallInstruction call , ReadSideEffectInstruction read , InitializeIndirectionInstruction init
205- |
206- init = succ and
207- init .getEnclosingFunction ( ) = call .getStaticCallTarget ( ) and
208- read .getPrimaryInstruction ( ) = call and
209- read .getSideEffectOperand ( ) .getAnyDef ( ) = instr
210- |
211- exists ( int n |
212- read .getIndex ( ) = n and
213- init .getParameter ( ) .getIndex ( ) = unbind ( n )
214- )
215- or
216- call .getThisArgument ( ) = instr and
217- init .getIRVariable ( ) instanceof IRThisVariable
218- )
219- )
220- }
221-
222- /**
223- * Holds if there exists an initialization of a `this` pointer of type `sourceClass` that flows
224- * to `instr`, and `instr` flows to `succ` and `succ`.
225- */
226- predicate successorFwd ( Instruction instr , Instruction succ , Class sourceClass ) {
227- flowsFromSource ( _, instr , sourceClass ) and
228- (
229- irBbPostDominates ( succ .getBlock ( ) , instr .getBlock ( ) ) and
230- (
231- (
232- succ .( CopyInstruction ) .getSourceValue ( ) = instr or
233- succ .( CheckedConvertOrNullInstruction ) .getUnary ( ) = instr or
234- succ .( ChiInstruction ) .getTotal ( ) = instr or
235- succ .( ConvertInstruction ) .getUnary ( ) = instr
236- )
237- or
238- succ .( InheritanceConversionInstruction ) .getUnary ( ) = instr
239- )
240- or
241- flowThroughCallableFwd ( instr , succ , sourceClass )
242- )
243- }
168+ predicate successorTC ( Instruction i1 , Instruction i2 ) = fastTC( successor / 2 ) ( i1 , i2 )
244169
245170/**
246- * Holds if `instr` is in the path from an initialization of a `this` pointer in a subclass, to a use
247- * of the `this` pointer in a baseclass.
171+ * Holds if:
172+ * - `source` is an initialization of a `this` pointer of type `sourceClass`, and
173+ * - `sink` is a use of the `this` pointer as type `sinkClass`, and
174+ * - `call` invokes a pure virtual function using `sink` as the `this` pointer, and
175+ * - `msg` is a string describing whether `source` is from a constructor or destructor.
248176 */
249- predicate isInPath ( Instruction instr ) {
250- exists ( Class sourceClass , Class sinkClass |
251- flowsFromSource ( _, instr , sourceClass ) and
252- flowsToSink ( instr , _, sinkClass ) and
253- sourceClass .getABaseClass + ( ) = sinkClass
254- )
177+ predicate flows (
178+ Instruction source , string msg , Class sourceClass , Instruction sink , CallInstruction call ,
179+ Class sinkClass
180+ ) {
181+ isSource ( source , msg , sourceClass ) and
182+ successorTC ( source , sink ) and
183+ isSink ( sink , call , sinkClass )
255184}
256185
257186query predicate edges ( Instruction a , Instruction b ) {
258- successor ( a , b , _ ) and isInPath ( a ) and isInPath ( b )
187+ successor ( a , b ) and flowsFromSource ( a ) and flowsFromSource ( b )
259188}
260189
261190query predicate nodes ( Instruction n , string key , string val ) {
262- isInPath ( n ) and key = "semmle.label" and val = n .toString ( )
191+ flowsFromSource ( n ) and
192+ flowsToSink ( n ) and
193+ key = "semmle.label" and
194+ val = n .toString ( )
263195}
264196
265197from
266198 Instruction source , Instruction sink , CallInstruction call , string msg , Class sourceClass ,
267199 Class sinkClass
268200where
269- isSource ( source , msg , sourceClass ) and
270- flowsToSink ( source , sink , sinkClass ) and
271- isSink ( sink , call , sinkClass ) and
201+ flows ( source , msg , sourceClass , sink , call , sinkClass ) and
272202 sourceClass .getABaseClass + ( ) = sinkClass
273203select call .getUnconvertedResultExpression ( ) , source , sink ,
274204 "Call to pure virtual function during " + msg
0 commit comments