@@ -128,6 +128,8 @@ private module Cached {
128
128
n = member .getBase ( ) and
129
129
not member .isStatic ( )
130
130
)
131
+ or
132
+ n = any ( CfgNodes:: ExprNodes:: IndexCfgNode index ) .getBase ( )
131
133
}
132
134
133
135
cached
@@ -219,23 +221,51 @@ private module Cached {
219
221
}
220
222
221
223
cached
222
- newtype TContentSet = TSingletonContent ( Content c )
224
+ newtype TContentSet =
225
+ TSingletonContent ( Content c ) or
226
+ TAnyElementContent ( ) or
227
+ TKnownOrUnknownElementContent ( Content:: KnownElementContent c )
228
+
229
+ private predicate trackKnownValue ( ConstantValue cv ) {
230
+ exists ( cv .asString ( ) )
231
+ or
232
+ cv .asInt ( ) = [ 0 .. 10 ]
233
+ }
223
234
224
235
cached
225
236
newtype TContent =
226
237
TFieldContent ( string name ) {
227
238
name = any ( PropertyMember member ) .getName ( )
228
239
or
229
240
name = any ( MemberExpr me ) .getMemberName ( )
230
- }
241
+ } or
242
+ TKnownElementContent ( ConstantValue cv ) { trackKnownValue ( cv ) } or
243
+ TUnknownElementContent ( )
231
244
232
245
cached
233
- newtype TContentApprox = TNonElementContentApprox ( Content c )
246
+ newtype TContentApprox =
247
+ TNonElementContentApprox ( Content c ) { not c instanceof Content:: ElementContent } or
248
+ TUnknownElementContentApprox ( ) or
249
+ TKnownIntegerElementContentApprox ( ) or
250
+ TKnownElementContentApprox ( string approx ) { approx = approxKnownElementIndex ( _) }
234
251
235
252
cached
236
253
newtype TDataFlowType = TUnknownDataFlowType ( )
237
254
}
238
255
256
+ class TElementContent = TKnownElementContent or TUnknownElementContent ;
257
+
258
+ /** Gets a string for approximating known element indices. */
259
+ private string approxKnownElementIndex ( ConstantValue cv ) {
260
+ not exists ( cv .asInt ( ) ) and
261
+ exists ( string s | s = cv .serialize ( ) |
262
+ s .length ( ) < 2 and
263
+ result = s
264
+ or
265
+ result = s .prefix ( 2 )
266
+ )
267
+ }
268
+
239
269
import Cached
240
270
241
271
/** Holds if `n` should be hidden from path explanations. */
@@ -477,26 +507,54 @@ predicate jumpStep(Node pred, Node succ) {
477
507
* content `c`.
478
508
*/
479
509
predicate storeStep ( Node node1 , ContentSet c , Node node2 ) {
480
- node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) =
481
- any ( CfgNodes:: ExprNodes:: MemberCfgNode var |
482
- exists ( CfgNodes:: StmtNodes:: AssignStmtCfgNode assign |
483
- var = assign .getLeftHandSide ( ) and
484
- node1 .asStmt ( ) = assign .getRightHandSide ( )
485
- |
486
- c .isSingleton ( any ( Content:: FieldContent ct | ct .getName ( ) = var .getMemberName ( ) ) )
487
- )
488
- ) .getBase ( )
510
+ exists ( CfgNodes:: ExprNodes:: MemberCfgWriteAccessNode var , Content:: FieldContent fc |
511
+ node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = var .getBase ( ) and
512
+ node1 .asStmt ( ) = var .getAssignStmt ( ) .getRightHandSide ( ) and
513
+ fc .getName ( ) = var .getMemberName ( ) and
514
+ c .isSingleton ( fc )
515
+ )
516
+ or
517
+ exists (
518
+ CfgNodes:: ExprNodes:: IndexCfgWriteNode var , Content:: KnownElementContent ec , int index ,
519
+ CfgNodes:: ExprCfgNode e
520
+ |
521
+ node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = var .getBase ( ) and
522
+ node1 .asStmt ( ) = var .getAssignStmt ( ) .getRightHandSide ( ) and
523
+ c .isKnownOrUnknownElement ( ec ) and
524
+ index = ec .getIndex ( ) .asInt ( ) and
525
+ e = var .getIndex ( )
526
+ |
527
+ index = e .getValue ( ) .asInt ( )
528
+ or
529
+ not exists ( e .getValue ( ) .asInt ( ) )
530
+ )
489
531
}
490
532
491
533
/**
492
534
* Holds if there is a read step of content `c` from `node1` to `node2`.
493
535
*/
494
536
predicate readStep ( Node node1 , ContentSet c , Node node2 ) {
495
- node2 .asExpr ( ) =
496
- any ( CfgNodes:: ExprNodes:: MemberCfgReadAccessNode var |
497
- node1 .asExpr ( ) = var .getBase ( ) and
498
- c .isSingleton ( any ( Content:: FieldContent ct | ct .getName ( ) = var .getMemberName ( ) ) )
499
- )
537
+ exists ( CfgNodes:: ExprNodes:: MemberCfgReadAccessNode var , Content:: FieldContent fc |
538
+ node2 .asExpr ( ) = var and
539
+ node1 .asExpr ( ) = var .getBase ( ) and
540
+ fc .getName ( ) = var .getMemberName ( ) and
541
+ c .isSingleton ( fc )
542
+ )
543
+ or
544
+ exists (
545
+ CfgNodes:: ExprNodes:: IndexCfgReadNode var , Content:: KnownElementContent ec , int index ,
546
+ CfgNodes:: ExprCfgNode e
547
+ |
548
+ node2 .asExpr ( ) = var and
549
+ node1 .asExpr ( ) = var .getBase ( ) and
550
+ c .isKnownOrUnknownElement ( ec ) and
551
+ index = ec .getIndex ( ) .asInt ( ) and
552
+ e = var .getIndex ( )
553
+ |
554
+ index = e .getValue ( ) .asInt ( )
555
+ or
556
+ not exists ( e .getValue ( ) .asInt ( ) )
557
+ )
500
558
}
501
559
502
560
/**
@@ -584,7 +642,7 @@ class DataFlowExpr = CfgNodes::ExprCfgNode;
584
642
* Holds if access paths with `c` at their head always should be tracked at high
585
643
* precision. This disables adaptive access path precision for such access paths.
586
644
*/
587
- predicate forceHighPrecision ( Content c ) { none ( ) }
645
+ predicate forceHighPrecision ( Content c ) { c instanceof Content :: ElementContent }
588
646
589
647
class NodeRegion instanceof Unit {
590
648
string toString ( ) { result = "NodeRegion" }
@@ -653,7 +711,18 @@ class ContentApprox extends TContentApprox {
653
711
}
654
712
655
713
/** Gets an approximated value for content `c`. */
656
- ContentApprox getContentApprox ( Content c ) { result = TNonElementContentApprox ( c ) }
714
+ ContentApprox getContentApprox ( Content c ) {
715
+ c instanceof Content:: UnknownElementContent and
716
+ result = TUnknownElementContentApprox ( )
717
+ or
718
+ exists ( c .( Content:: KnownElementContent ) .getIndex ( ) .asInt ( ) ) and
719
+ result = TKnownIntegerElementContentApprox ( )
720
+ or
721
+ result =
722
+ TKnownElementContentApprox ( approxKnownElementIndex ( c .( Content:: KnownElementContent ) .getIndex ( ) ) )
723
+ or
724
+ result = TNonElementContentApprox ( c )
725
+ }
657
726
658
727
/**
659
728
* A unit class for adding additional jump steps.
0 commit comments