@@ -693,6 +693,7 @@ class ClassNode extends DataFlow::SourceNode {
693693 /**
694694 * Gets a dataflow node that refers to this class object.
695695 */
696+ cached
696697 DataFlow:: SourceNode getAClassReference ( ) {
697698 result = getAClassReference ( DataFlow:: TypeTracker:: end ( ) )
698699 }
@@ -709,6 +710,15 @@ class ClassNode extends DataFlow::SourceNode {
709710 t .start ( ) and
710711 result = getAReceiverNode ( )
711712 or
713+ // Use a parameter type as starting point of type tracking.
714+ // Use `t.call()` to emulate the value being passed in through an unseen
715+ // call site, but not out of the call again.
716+ t .call ( ) and
717+ exists ( Parameter param |
718+ this = param .getTypeAnnotation ( ) .getClass ( ) and
719+ result = DataFlow:: parameterNode ( param )
720+ )
721+ or
712722 result = getAnInstanceReferenceAux ( t ) and
713723 // Avoid tracking into the receiver of other classes.
714724 // Note that this also blocks flows into a property of the receiver,
@@ -724,6 +734,7 @@ class ClassNode extends DataFlow::SourceNode {
724734 /**
725735 * Gets a dataflow node that refers to an instance of this class.
726736 */
737+ cached
727738 DataFlow:: SourceNode getAnInstanceReference ( ) {
728739 result = getAnInstanceReference ( DataFlow:: TypeTracker:: end ( ) )
729740 }
@@ -844,6 +855,12 @@ module ClassNode {
844855 override DataFlow:: Node getASuperClassNode ( ) { result = astNode .getSuperClass ( ) .flow ( ) }
845856 }
846857
858+ private DataFlow:: PropRef getAPrototypeReferenceInFile ( string name , File f ) {
859+ GlobalAccessPath:: getAccessPath ( result .getBase ( ) ) = name and
860+ result .getPropertyName ( ) = "prototype" and
861+ result .getFile ( ) = f
862+ }
863+
847864 /**
848865 * A function definition with prototype manipulation as a `ClassNode` instance.
849866 */
@@ -854,9 +871,16 @@ module ClassNode {
854871
855872 FunctionStyleClass ( ) {
856873 function .getFunction ( ) = astNode and
857- exists ( DataFlow:: PropRef read |
858- read .getPropertyName ( ) = "prototype" and
859- read .getBase ( ) .analyze ( ) .getAValue ( ) = function
874+ (
875+ exists ( DataFlow:: PropRef read |
876+ read .getPropertyName ( ) = "prototype" and
877+ read .getBase ( ) .analyze ( ) .getAValue ( ) = function
878+ )
879+ or
880+ exists ( string name |
881+ name = GlobalAccessPath:: fromRhs ( this ) and
882+ exists ( getAPrototypeReferenceInFile ( name , getFile ( ) ) )
883+ )
860884 )
861885 }
862886
@@ -916,11 +940,16 @@ module ClassNode {
916940 result = base .getAPropertyRead ( "prototype" )
917941 or
918942 result = base .getAPropertySource ( "prototype" )
919- or
920- exists ( ExtendCall call |
921- call .getDestinationOperand ( ) = base .getAPropertyRead ( "prototype" ) and
922- result = call .getASourceOperand ( )
923- )
943+ )
944+ or
945+ exists ( string name |
946+ GlobalAccessPath:: fromRhs ( this ) = name and
947+ result = getAPrototypeReferenceInFile ( name , getFile ( ) )
948+ )
949+ or
950+ exists ( ExtendCall call |
951+ call .getDestinationOperand ( ) = getAPrototypeReference ( ) and
952+ result = call .getASourceOperand ( )
924953 )
925954 }
926955
0 commit comments