@@ -13,7 +13,9 @@ private import semmle.code.cpp.models.interfaces.DataFlow
13
13
14
14
private newtype TIRDataFlowNode =
15
15
TInstructionNode ( Instruction i ) or
16
- TVariableNode ( Variable var )
16
+ TVariableNode ( Variable var ) or
17
+ TSynthesizedStoreNode ( StoreChain chain ) or
18
+ TSynthesizedLoadNode ( LoadChain load )
17
19
18
20
/**
19
21
* A node in a data flow graph.
@@ -71,9 +73,7 @@ class Node extends TIRDataFlowNode {
71
73
* `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
72
74
* a partial definition of `&x`).
73
75
*/
74
- Expr asPartialDefinition ( ) {
75
- result = this .( PartialDefinitionNode ) .getInstruction ( ) .getUnconvertedResultExpression ( )
76
- }
76
+ Expr asPartialDefinition ( ) { result = this .( PartialDefinitionNode ) .getDefiningExpr ( ) }
77
77
78
78
/**
79
79
* DEPRECATED: See UninitializedNode.
@@ -231,7 +231,7 @@ deprecated class UninitializedNode extends Node {
231
231
* This class exists to match the interface used by Java. There are currently no non-abstract
232
232
* classes that extend it. When we implement field flow, we can revisit this.
233
233
*/
234
- abstract class PostUpdateNode extends InstructionNode {
234
+ abstract class PostUpdateNode extends Node {
235
235
/**
236
236
* Gets the node before the state update.
237
237
*/
@@ -251,42 +251,8 @@ abstract class PostUpdateNode extends InstructionNode {
251
251
* setY(&x); // a partial definition of the object `x`.
252
252
* ```
253
253
*/
254
- abstract private class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
255
-
256
- private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257
- override ChiInstruction instr ;
258
-
259
- ExplicitFieldStoreQualifierNode ( ) {
260
- not instr .isResultConflated ( ) and
261
- exists ( StoreInstruction store , FieldInstruction field |
262
- instr .getPartial ( ) = store and field = store .getDestinationAddress ( )
263
- )
264
- }
265
-
266
- // There might be multiple `ChiInstructions` that has a particular instruction as
267
- // the total operand - so this definition gives consistency errors in
268
- // DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269
- // this consistency failure has.
270
- override Node getPreUpdateNode ( ) { result .asInstruction ( ) = instr .getTotal ( ) }
271
- }
272
-
273
- /**
274
- * Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
275
- * For instance, an update to a field of a struct containing only one field. For these cases we
276
- * attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
277
- * (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
278
- */
279
- private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
280
- override StoreInstruction instr ;
281
-
282
- ExplicitSingleFieldStoreQualifierNode ( ) {
283
- exists ( FieldAddressInstruction field |
284
- field = instr .getDestinationAddress ( ) and
285
- not exists ( ChiInstruction chi | chi .getPartial ( ) = instr )
286
- )
287
- }
288
-
289
- override Node getPreUpdateNode ( ) { none ( ) }
254
+ abstract private class PartialDefinitionNode extends PostUpdateNode {
255
+ abstract Expr getDefiningExpr ( ) ;
290
256
}
291
257
292
258
/**
@@ -368,18 +334,225 @@ class VariableNode extends Node, TVariableNode {
368
334
override string toString ( ) { result = v .toString ( ) }
369
335
}
370
336
337
+ /** The target node of a `readStep`. */
371
338
abstract class ReadStepNode extends Node {
339
+ /** Get the field that is read. */
372
340
abstract Field getAField ( ) ;
373
341
342
+ /** Get the node representing the value that is read. */
374
343
abstract Node getReadValue ( ) ;
375
344
}
376
345
346
+ /** The target node of a `storeStep`. */
377
347
abstract class StoreStepNode extends PostUpdateNode {
348
+ /** Get the field that is stored into. */
378
349
abstract Field getAField ( ) ;
379
350
351
+ /** Get the node representing the value that is stored. */
380
352
abstract Node getStoredValue ( ) ;
381
353
}
382
354
355
+ private newtype TStoreChain =
356
+ TStore ( FieldInstruction f , StoreInstruction store , ChiInstruction chi ) {
357
+ not chi .isResultConflated ( ) and
358
+ chi .getPartial ( ) = store and
359
+ store .getDestinationAddress ( ) = f
360
+ } or
361
+ TStoreCons ( FieldInstruction f , TStoreChain next ) {
362
+ next = TStoreCons ( f .getAUse ( ) .getUse ( ) , _) or
363
+ next = TStore ( f .getAUse ( ) .getUse ( ) , _, _)
364
+ }
365
+
366
+ private class StoreChain extends TStoreChain {
367
+ string toString ( ) { none ( ) }
368
+
369
+ StoreChainCons getParent ( ) { none ( ) }
370
+
371
+ StoreChain getChild ( ) { none ( ) }
372
+
373
+ StoreInstruction getStoreInstruction ( ) { none ( ) }
374
+
375
+ ChiInstruction getChiInstruction ( ) { none ( ) }
376
+
377
+ FieldInstruction getFieldInstruction ( ) { none ( ) }
378
+ }
379
+
380
+ private class StoreChainNil extends StoreChain , TStore {
381
+ FieldInstruction f ;
382
+ StoreInstruction store ;
383
+ ChiInstruction chi ;
384
+
385
+ StoreChainNil ( ) { this = TStore ( f , store , chi ) }
386
+
387
+ override string toString ( ) { result = f .getField ( ) .toString ( ) }
388
+
389
+ override StoreChainCons getParent ( ) { result = TStoreCons ( _, this ) }
390
+
391
+ override StoreInstruction getStoreInstruction ( ) { result = store }
392
+
393
+ override ChiInstruction getChiInstruction ( ) { result = chi }
394
+
395
+ override FieldInstruction getFieldInstruction ( ) { result = f }
396
+ }
397
+
398
+ private class StoreChainCons extends StoreChain , TStoreCons {
399
+ FieldInstruction f ;
400
+ StoreChain next ;
401
+
402
+ StoreChainCons ( ) { this = TStoreCons ( f , next ) }
403
+
404
+ override string toString ( ) { result = f .getField ( ) .toString ( ) + "." + next .toString ( ) }
405
+
406
+ override StoreChainCons getParent ( ) { result .getChild ( ) = this }
407
+
408
+ override StoreChain getChild ( ) { result = next }
409
+
410
+ override FieldInstruction getFieldInstruction ( ) { result = f }
411
+
412
+ override StoreInstruction getStoreInstruction ( ) { result = next .getStoreInstruction ( ) }
413
+
414
+ override ChiInstruction getChiInstruction ( ) { result = next .getChiInstruction ( ) }
415
+ }
416
+
417
+ private Instruction getAUse ( FieldAddressInstruction fa ) { result = fa .getAUse ( ) .getUse ( ) }
418
+
419
+ private newtype TLoadChain =
420
+ TLoad ( FieldAddressInstruction f ) {
421
+ not f .getObjectAddress ( ) instanceof FieldInstruction and getAUse * ( f ) instanceof LoadInstruction
422
+ } or
423
+ TLoadChainCons ( FieldAddressInstruction f , TLoadChain prev ) {
424
+ prev = TLoadChainCons ( f .getObjectAddress ( ) , _) or
425
+ prev = TLoad ( f .getObjectAddress ( ) )
426
+ }
427
+
428
+ private class LoadChain extends TLoadChain {
429
+ string toString ( ) { none ( ) }
430
+
431
+ LoadInstruction getLoadInstruction ( ) { none ( ) }
432
+
433
+ LoadChainCons getParent ( ) { none ( ) }
434
+
435
+ LoadChain getChild ( ) { none ( ) }
436
+
437
+ FieldInstruction getFieldInstruction ( ) { none ( ) }
438
+ }
439
+
440
+ private class LoadNil extends LoadChain , TLoad {
441
+ FieldInstruction f ;
442
+
443
+ LoadNil ( ) { this = TLoad ( f ) }
444
+
445
+ override string toString ( ) { result = f .getField ( ) .toString ( ) }
446
+
447
+ override LoadChainCons getParent ( ) { result = TLoadChainCons ( _, this ) }
448
+
449
+ override LoadInstruction getLoadInstruction ( ) {
450
+ result .getSourceAddressOperand ( ) .getAnyDef ( ) = f
451
+ or
452
+ result = getParent ( ) .getLoadInstruction ( )
453
+ }
454
+
455
+ override FieldInstruction getFieldInstruction ( ) { result = f }
456
+ }
457
+
458
+ private class LoadChainCons extends LoadChain , TLoadChainCons {
459
+ FieldInstruction f ;
460
+ LoadChain prev ;
461
+
462
+ LoadChainCons ( ) { this = TLoadChainCons ( f , prev ) }
463
+
464
+ override string toString ( ) { result = prev .toString ( ) + "." + f .getField ( ) .toString ( ) }
465
+
466
+ override LoadInstruction getLoadInstruction ( ) {
467
+ result .getSourceAddressOperand ( ) .getAnyDef ( ) = f
468
+ or
469
+ result = getParent ( ) .getLoadInstruction ( )
470
+ }
471
+
472
+ override LoadChainCons getParent ( ) { result .getChild ( ) = this }
473
+
474
+ override LoadChain getChild ( ) { result = prev }
475
+
476
+ override FieldInstruction getFieldInstruction ( ) { result = f }
477
+ }
478
+
479
+ private class SynthesizedStoreNode extends TSynthesizedStoreNode , StoreStepNode , ReadStepNode ,
480
+ PartialDefinitionNode {
481
+ StoreChain storeChain ;
482
+
483
+ SynthesizedStoreNode ( ) { this = TSynthesizedStoreNode ( storeChain ) }
484
+
485
+ override string toString ( ) { result = "[" + storeChain .toString ( ) + "] (store)" }
486
+
487
+ StoreChain getStoreChain ( ) { result = storeChain }
488
+
489
+ ChiInstruction getChiInstruction ( ) { result = storeChain .getChiInstruction ( ) }
490
+
491
+ StoreInstruction getStoreInstruction ( ) { result = storeChain .getStoreInstruction ( ) }
492
+
493
+ override Node getPreUpdateNode ( ) {
494
+ result .( SynthesizedStoreNode ) .getStoreChain ( ) = storeChain .getParent ( )
495
+ or
496
+ not exists ( storeChain .getParent ( ) ) and
497
+ result .asInstruction ( ) = this .getChiInstruction ( ) .getTotal ( )
498
+ }
499
+
500
+ override Field getAField ( ) { result = storeChain .getFieldInstruction ( ) .getField ( ) }
501
+
502
+ override Node getStoredValue ( ) {
503
+ // Only the "end" of the chain stores a value (i.e., can be the target of a store step)
504
+ not exists ( storeChain .getChild ( ) ) and result .asInstruction ( ) = this .getStoreInstruction ( )
505
+ }
506
+
507
+ override Node getReadValue ( ) {
508
+ result .( SynthesizedStoreNode ) .getStoreChain ( ) = storeChain .getParent ( )
509
+ or
510
+ not exists ( storeChain .getParent ( ) ) and
511
+ result .asInstruction ( ) = this .getChiInstruction ( ) .getTotal ( )
512
+ }
513
+
514
+ override Declaration getEnclosingCallable ( ) { result = this .getFunction ( ) }
515
+
516
+ override Function getFunction ( ) { result = this .getStoreInstruction ( ) .getEnclosingFunction ( ) }
517
+
518
+ override Type getType ( ) { result = this .getStoreInstruction ( ) .getResultType ( ) }
519
+
520
+ override Location getLocation ( ) { result = this .getStoreInstruction ( ) .getLocation ( ) }
521
+
522
+ override Expr getDefiningExpr ( ) {
523
+ result = this .getStoreInstruction ( ) .getSourceValue ( ) .getUnconvertedResultExpression ( )
524
+ }
525
+ }
526
+
527
+ private class SynthesizedLoadNode extends TSynthesizedLoadNode , ReadStepNode {
528
+ LoadChain loadChain ;
529
+
530
+ SynthesizedLoadNode ( ) { this = TSynthesizedLoadNode ( loadChain ) }
531
+
532
+ override Field getAField ( ) { result = loadChain .getFieldInstruction ( ) .getField ( ) }
533
+
534
+ override Node getReadValue ( ) {
535
+ result .( SynthesizedLoadNode ) .getLoadChain ( ) = loadChain .getChild ( )
536
+ or
537
+ not exists ( loadChain .getChild ( ) ) and
538
+ result .asInstruction ( ) = this .getLoadInstruction ( ) .getSourceValueOperand ( ) .getAnyDef ( )
539
+ }
540
+
541
+ LoadChain getLoadChain ( ) { result = loadChain }
542
+
543
+ LoadInstruction getLoadInstruction ( ) { result = loadChain .getLoadInstruction ( ) }
544
+
545
+ override string toString ( ) { result = "[" + loadChain .toString ( ) + "] (load)" }
546
+
547
+ override Declaration getEnclosingCallable ( ) { result = this .getFunction ( ) }
548
+
549
+ override Function getFunction ( ) { result = this .getLoadInstruction ( ) .getEnclosingFunction ( ) }
550
+
551
+ override Type getType ( ) { result = this .getLoadInstruction ( ) .getResultType ( ) }
552
+
553
+ override Location getLocation ( ) { result = this .getLoadInstruction ( ) .getLocation ( ) }
554
+ }
555
+
383
556
/**
384
557
* Gets the node corresponding to `instr`.
385
558
*/
@@ -433,6 +606,18 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
433
606
*/
434
607
predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
435
608
simpleInstructionLocalFlowStep ( nodeFrom .asInstruction ( ) , nodeTo .asInstruction ( ) )
609
+ or
610
+ exists ( SynthesizedStoreNode synthFrom |
611
+ synthFrom = nodeFrom and
612
+ not exists ( synthFrom .getStoreChain ( ) .getParent ( ) ) and
613
+ synthFrom .getChiInstruction ( ) = nodeTo .asInstruction ( )
614
+ )
615
+ or
616
+ exists ( SynthesizedLoadNode synthFrom |
617
+ synthFrom = nodeFrom and
618
+ not exists ( synthFrom .getLoadChain ( ) .getParent ( ) ) and
619
+ synthFrom .getLoadInstruction ( ) = nodeTo .asInstruction ( )
620
+ )
436
621
}
437
622
438
623
pragma [ noinline]
0 commit comments