@@ -112,11 +112,9 @@ class ReturnNode extends InstructionNode {
112112 Instruction primary ;
113113
114114 ReturnNode ( ) {
115- exists ( ReturnValueInstruction ret | instr = ret . getReturnValue ( ) and primary = ret )
115+ exists ( ReturnValueInstruction ret | instr = ret and primary = ret )
116116 or
117- exists ( ReturnIndirectionInstruction rii |
118- instr = rii .getSideEffectOperand ( ) .getAnyDef ( ) and primary = rii
119- )
117+ exists ( ReturnIndirectionInstruction rii | instr = rii and primary = rii )
120118 }
121119
122120 /** Gets the kind of this returned value. */
@@ -190,108 +188,16 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
190188 */
191189predicate jumpStep ( Node n1 , Node n2 ) { none ( ) }
192190
193- private predicate fieldStoreStepNoChi ( Node node1 , FieldContent f , PostUpdateNode node2 ) {
194- exists ( StoreInstruction store , Class c |
195- store = node2 .asInstruction ( ) and
196- store .getSourceValueOperand ( ) = node1 .asOperand ( ) and
197- getWrittenField ( store , f .getAField ( ) , c ) and
198- f .hasOffset ( c , _, _)
199- )
200- }
201-
202- private FieldAddressInstruction getFieldInstruction ( Instruction instr ) {
203- result = instr or
204- result = instr .( CopyValueInstruction ) .getUnary ( )
205- }
206-
207- pragma [ noinline]
208- private predicate getWrittenField ( Instruction instr , Field f , Class c ) {
209- exists ( FieldAddressInstruction fa |
210- fa =
211- getFieldInstruction ( [
212- instr .( StoreInstruction ) .getDestinationAddress ( ) ,
213- instr .( WriteSideEffectInstruction ) .getDestinationAddress ( )
214- ] ) and
215- f = fa .getField ( ) and
216- c = f .getDeclaringType ( )
217- )
218- }
219-
220- private predicate fieldStoreStepChi ( Node node1 , FieldContent f , PostUpdateNode node2 ) {
221- exists ( ChiPartialOperand operand , ChiInstruction chi |
222- chi .getPartialOperand ( ) = operand and
223- node1 .asOperand ( ) = operand and
224- node2 .asInstruction ( ) = chi and
225- exists ( Class c |
226- c = chi .getResultType ( ) and
227- exists ( int startBit , int endBit |
228- chi .getUpdatedInterval ( startBit , endBit ) and
229- f .hasOffset ( c , startBit , endBit )
230- )
231- or
232- getWrittenField ( operand .getDef ( ) , f .getAField ( ) , c ) and
233- f .hasOffset ( c , _, _)
234- )
235- )
236- }
237-
238- private predicate arrayStoreStepChi ( Node node1 , ArrayContent a , PostUpdateNode node2 ) {
239- exists ( a ) and
240- exists ( ChiPartialOperand operand , ChiInstruction chi , StoreInstruction store |
241- chi .getPartialOperand ( ) = operand and
242- store = operand .getDef ( ) and
243- node1 .asOperand ( ) = operand and
244- // This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
245- // and `PointerStoreNode` require it in their characteristic predicates.
246- node2 .asInstruction ( ) = chi and
247- (
248- // `x[i] = taint()`
249- // This matches the characteristic predicate in `ArrayStoreNode`.
250- store .getDestinationAddress ( ) instanceof PointerAddInstruction
251- or
252- // `*p = taint()`
253- // This matches the characteristic predicate in `PointerStoreNode`.
254- store .getDestinationAddress ( ) .( CopyValueInstruction ) .getUnary ( ) instanceof LoadInstruction
255- )
256- )
257- }
258-
259191/**
260192 * Holds if data can flow from `node1` to `node2` via an assignment to `f`.
261193 * Thus, `node2` references an object with a field `f` that contains the
262194 * value of `node1`.
263195 */
264- predicate storeStep ( Node node1 , Content f , PostUpdateNode node2 ) {
265- fieldStoreStepNoChi ( node1 , f , node2 ) or
266- fieldStoreStepChi ( node1 , f , node2 ) or
267- arrayStoreStepChi ( node1 , f , node2 ) or
268- fieldStoreStepAfterArraySuppression ( node1 , f , node2 )
269- }
270-
271- // This predicate pushes the correct `FieldContent` onto the access path when the
272- // `suppressArrayRead` predicate has popped off an `ArrayContent`.
273- private predicate fieldStoreStepAfterArraySuppression (
274- Node node1 , FieldContent f , PostUpdateNode node2
275- ) {
276- exists ( WriteSideEffectInstruction write , ChiInstruction chi , Class c |
277- not chi .isResultConflated ( ) and
278- node1 .asInstruction ( ) = chi and
279- node2 .asInstruction ( ) = chi and
280- chi .getPartial ( ) = write and
281- getWrittenField ( write , f .getAField ( ) , c ) and
282- f .hasOffset ( c , _, _)
283- )
284- }
285-
286- bindingset [ result , i]
287- private int unbindInt ( int i ) { i <= result and i >= result }
288-
289- pragma [ noinline]
290- private predicate getLoadedField ( LoadInstruction load , Field f , Class c ) {
291- exists ( FieldAddressInstruction fa |
292- fa = load .getSourceAddress ( ) and
293- f = fa .getField ( ) and
294- c = f .getDeclaringType ( )
196+ predicate storeStep ( StoreNodeInstr node1 , FieldContent f , StoreNodeInstr node2 ) {
197+ exists ( FieldAddressInstruction fai |
198+ node1 .getInstruction ( ) = fai and
199+ node2 .getInstruction ( ) = fai .getObjectAddress ( ) and
200+ f .getField ( ) = fai .getField ( )
295201 )
296202}
297203
@@ -300,122 +206,14 @@ private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
300206 * Thus, `node1` references an object with a field `f` whose value ends up in
301207 * `node2`.
302208 */
303- private predicate fieldReadStep ( Node node1 , FieldContent f , Node node2 ) {
304- exists ( LoadOperand operand |
305- node2 .asOperand ( ) = operand and
306- node1 .asInstruction ( ) = operand .getAnyDef ( ) and
307- exists ( Class c |
308- c = operand .getAnyDef ( ) .getResultType ( ) and
309- exists ( int startBit , int endBit |
310- operand .getUsedInterval ( unbindInt ( startBit ) , unbindInt ( endBit ) ) and
311- f .hasOffset ( c , startBit , endBit )
312- )
313- or
314- getLoadedField ( operand .getUse ( ) , f .getAField ( ) , c ) and
315- f .hasOffset ( c , _, _)
316- )
209+ predicate readStep ( ReadNode node1 , FieldContent f , ReadNode node2 ) {
210+ exists ( FieldAddressInstruction fai |
211+ node1 .getInstruction ( ) = fai .getObjectAddress ( ) and
212+ node2 .getInstruction ( ) = fai and
213+ f .getField ( ) = fai .getField ( )
317214 )
318215}
319216
320- /**
321- * When a store step happens in a function that looks like an array write such as:
322- * ```cpp
323- * void f(int* pa) {
324- * pa = source();
325- * }
326- * ```
327- * it can be a write to an array, but it can also happen that `f` is called as `f(&a.x)`. If that is
328- * the case, the `ArrayContent` that was written by the call to `f` should be popped off the access
329- * path, and a `FieldContent` containing `x` should be pushed instead.
330- * So this case pops `ArrayContent` off the access path, and the `fieldStoreStepAfterArraySuppression`
331- * predicate in `storeStep` ensures that we push the right `FieldContent` onto the access path.
332- */
333- predicate suppressArrayRead ( Node node1 , ArrayContent a , Node node2 ) {
334- exists ( a ) and
335- exists ( WriteSideEffectInstruction write , ChiInstruction chi |
336- node1 .asInstruction ( ) = write and
337- node2 .asInstruction ( ) = chi and
338- chi .getPartial ( ) = write and
339- getWrittenField ( write , _, _)
340- )
341- }
342-
343- private class ArrayToPointerConvertInstruction extends ConvertInstruction {
344- ArrayToPointerConvertInstruction ( ) {
345- this .getUnary ( ) .getResultType ( ) instanceof ArrayType and
346- this .getResultType ( ) instanceof PointerType
347- }
348- }
349-
350- private Instruction skipOneCopyValueInstructionRec ( CopyValueInstruction copy ) {
351- copy .getUnary ( ) = result and not result instanceof CopyValueInstruction
352- or
353- result = skipOneCopyValueInstructionRec ( copy .getUnary ( ) )
354- }
355-
356- private Instruction skipCopyValueInstructions ( Operand op ) {
357- not result instanceof CopyValueInstruction and result = op .getDef ( )
358- or
359- result = skipOneCopyValueInstructionRec ( op .getDef ( ) )
360- }
361-
362- private predicate arrayReadStep ( Node node1 , ArrayContent a , Node node2 ) {
363- exists ( a ) and
364- // Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
365- exists ( LoadOperand operand , Instruction address |
366- operand .isDefinitionInexact ( ) and
367- node1 .asInstruction ( ) = operand .getAnyDef ( ) and
368- operand = node2 .asOperand ( ) and
369- address = skipCopyValueInstructions ( operand .getAddressOperand ( ) ) and
370- (
371- address instanceof LoadInstruction or
372- address instanceof ArrayToPointerConvertInstruction or
373- address instanceof PointerOffsetInstruction
374- )
375- )
376- }
377-
378- /**
379- * In cases such as:
380- * ```cpp
381- * void f(int* pa) {
382- * *pa = source();
383- * }
384- * ...
385- * int x;
386- * f(&x);
387- * use(x);
388- * ```
389- * the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition
390- * is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
391- * from the access path.
392- */
393- private predicate exactReadStep ( Node node1 , ArrayContent a , Node node2 ) {
394- exists ( a ) and
395- exists ( WriteSideEffectInstruction write , ChiInstruction chi |
396- not chi .isResultConflated ( ) and
397- chi .getPartial ( ) = write and
398- node1 .asInstruction ( ) = write and
399- node2 .asInstruction ( ) = chi and
400- // To distinquish this case from the `arrayReadStep` case we require that the entire variable was
401- // overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the
402- // entire variable).
403- exists ( LoadInstruction load | load .getSourceValue ( ) = chi )
404- )
405- }
406-
407- /**
408- * Holds if data can flow from `node1` to `node2` via a read of `f`.
409- * Thus, `node1` references an object with a field `f` whose value ends up in
410- * `node2`.
411- */
412- predicate readStep ( Node node1 , Content f , Node node2 ) {
413- fieldReadStep ( node1 , f , node2 ) or
414- arrayReadStep ( node1 , f , node2 ) or
415- exactReadStep ( node1 , f , node2 ) or
416- suppressArrayRead ( node1 , f , node2 )
417- }
418-
419217/**
420218 * Holds if values stored inside content `c` are cleared at node `n`.
421219 */
@@ -447,7 +245,7 @@ private predicate suppressUnusedNode(Node n) { any() }
447245// Java QL library compatibility wrappers
448246//////////////////////////////////////////////////////////////////////////////
449247/** A node that performs a type cast. */
450- class CastNode extends InstructionNode {
248+ class CastNode extends Node {
451249 CastNode ( ) { none ( ) } // stub implementation
452250}
453251
0 commit comments