@@ -337,7 +337,7 @@ private predicate exactTypeBase(TypeFlowNode n, RefType t) {
337
337
n .asExpr ( ) = e and
338
338
e .getType ( ) = t and
339
339
not e instanceof FunctionalExpr and
340
- exists ( RefType sub | sub .getASourceSupertype ( ) = t .getSourceDeclaration ( ) )
340
+ exists ( SrcRefType sub | sub .getASourceSupertype ( ) = t .getSourceDeclaration ( ) )
341
341
)
342
342
}
343
343
@@ -384,17 +384,23 @@ private predicate upcastCand(TypeFlowNode n, RefType t1, RefType t1e, RefType t2
384
384
)
385
385
}
386
386
387
+ private predicate unconstrained ( BoundedType t ) {
388
+ t .( Wildcard ) .isUnconstrained ( )
389
+ or
390
+ t .( BoundedType ) .getUpperBoundType ( ) instanceof TypeObject and
391
+ not t .( Wildcard ) .hasLowerBound ( )
392
+ or
393
+ unconstrained ( t .( BoundedType ) .getUpperBoundType ( ) )
394
+ or
395
+ unconstrained ( t .( Wildcard ) .getLowerBoundType ( ) )
396
+ }
397
+
387
398
/** Holds if `t` is a raw type or parameterised type with unrestricted type arguments. */
388
399
private predicate unbound ( RefType t ) {
389
400
t instanceof RawType
390
401
or
391
402
exists ( ParameterizedType pt | pt = t |
392
- forex ( RefType arg | arg = pt .getATypeArgument ( ) |
393
- arg .( Wildcard ) .isUnconstrained ( )
394
- or
395
- arg .( BoundedType ) .getUpperBoundType ( ) instanceof TypeObject and
396
- not arg .( Wildcard ) .hasLowerBound ( )
397
- )
403
+ forex ( RefType arg | arg = pt .getATypeArgument ( ) | unconstrained ( arg ) )
398
404
)
399
405
}
400
406
@@ -492,9 +498,10 @@ predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
492
498
493
499
/**
494
500
* Holds if `n` has type `t` and this information is discarded, such that `t`
495
- * might be a better type bound for nodes where `n` flows to.
501
+ * might be a better type bound for nodes where `n` flows to. This might include
502
+ * multiple bounds for a single node.
496
503
*/
497
- private predicate typeFlowBase ( TypeFlowNode n , RefType t ) {
504
+ private predicate typeFlowBaseCand ( TypeFlowNode n , RefType t ) {
498
505
exists ( RefType srctype |
499
506
upcast ( n , srctype ) or
500
507
upcastEnhancedForStmt ( n .asSsa ( ) , srctype ) or
@@ -509,6 +516,26 @@ private predicate typeFlowBase(TypeFlowNode n, RefType t) {
509
516
)
510
517
}
511
518
519
+ /**
520
+ * Holds if `n` has type `t` and this information is discarded, such that `t`
521
+ * might be a better type bound for nodes where `n` flows to. This only includes
522
+ * the best such bound for each node.
523
+ */
524
+ private predicate typeFlowBase ( TypeFlowNode n , RefType t ) {
525
+ exists ( RefType te |
526
+ typeFlowBaseCand ( n , t ) and
527
+ te = t .getErasure ( ) and
528
+ not exists ( RefType better |
529
+ typeFlowBaseCand ( n , better ) and
530
+ better != t and
531
+ not t .getASupertype + ( ) = better
532
+ |
533
+ better .getASupertype + ( ) = t or
534
+ better .getErasure ( ) .( RefType ) .getASourceSupertype + ( ) = te
535
+ )
536
+ )
537
+ }
538
+
512
539
private module TypeFlowPropagation implements TypePropagation {
513
540
predicate candType = typeFlow / 2 ;
514
541
0 commit comments