@@ -337,7 +337,7 @@ private predicate exactTypeBase(TypeFlowNode n, RefType t) {
337337 n .asExpr ( ) = e and
338338 e .getType ( ) = t and
339339 not e instanceof FunctionalExpr and
340- exists ( RefType sub | sub .getASourceSupertype ( ) = t .getSourceDeclaration ( ) )
340+ exists ( SrcRefType sub | sub .getASourceSupertype ( ) = t .getSourceDeclaration ( ) )
341341 )
342342}
343343
@@ -384,17 +384,23 @@ private predicate upcastCand(TypeFlowNode n, RefType t1, RefType t1e, RefType t2
384384 )
385385}
386386
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+
387398/** Holds if `t` is a raw type or parameterised type with unrestricted type arguments. */
388399private predicate unbound ( RefType t ) {
389400 t instanceof RawType
390401 or
391402 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 ) )
398404 )
399405}
400406
@@ -492,9 +498,10 @@ predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
492498
493499/**
494500 * 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.
496503 */
497- private predicate typeFlowBase ( TypeFlowNode n , RefType t ) {
504+ private predicate typeFlowBaseCand ( TypeFlowNode n , RefType t ) {
498505 exists ( RefType srctype |
499506 upcast ( n , srctype ) or
500507 upcastEnhancedForStmt ( n .asSsa ( ) , srctype ) or
@@ -509,6 +516,26 @@ private predicate typeFlowBase(TypeFlowNode n, RefType t) {
509516 )
510517}
511518
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+
512539private module TypeFlowPropagation implements TypePropagation {
513540 predicate candType = typeFlow / 2 ;
514541
0 commit comments