@@ -13,6 +13,7 @@ private import sharedlib.FlowSummaryImpl as FlowSummaryImpl
1313private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate
1414private import semmle.javascript.dataflow.FlowSummary as FlowSummary
1515private import semmle.javascript.dataflow.internal.BarrierGuards
16+ private import codeql.util.Boolean
1617
1718class DataFlowSecondLevelScope = Unit ;
1819
@@ -381,6 +382,8 @@ predicate postUpdatePair(Node pre, Node post) {
381382 pre .( FlowSummaryNode ) .getSummaryNode ( ) )
382383 or
383384 VariableCaptureOutput:: capturePostUpdateNode ( getClosureNode ( post ) , getClosureNode ( pre ) )
385+ or
386+ any ( AdditionalFlowInternal f ) .postUpdate ( pre , post )
384387}
385388
386389class CastNode extends DataFlow:: Node {
@@ -391,17 +394,12 @@ cached
391394newtype TDataFlowCallable =
392395 MkSourceCallable ( StmtContainer container ) or
393396 MkLibraryCallable ( LibraryCallable callable ) or
394- MkClassHarnessCallable ( Function f ) {
395- // We only need a class harness for functions that act as classes (i.e. constructors),
396- // but since DataFlow::Node has not been materialised at this stage, we can't use DataFlow::ClassNode.
397- // Exclude arrow functions as they can't be called with 'new'.
398- not f instanceof ArrowFunctionExpr and
399- // We also don't need harnesses for externs
400- not f .getTopLevel ( ) .isExterns ( )
397+ MkGenericSynthesizedCallable ( AstNode node , string tag ) {
398+ any ( AdditionalFlowInternal f ) .needsSynthesizedCallable ( node , tag )
401399 }
402400
403401/**
404- * A callable entity. This is a wrapper around either a `StmtContainer` or a `LibraryCallable`.
402+ * A callable entity.
405403 */
406404class DataFlowCallable extends TDataFlowCallable {
407405 /** Gets a string representation of this callable. */
@@ -410,19 +408,26 @@ class DataFlowCallable extends TDataFlowCallable {
410408 or
411409 result = this .asLibraryCallable ( )
412410 or
413- result = this .asClassHarness ( ) . toString ( )
411+ this .isGenericSynthesizedCallable ( _ , result )
414412 }
415413
416414 /** Gets the location of this callable, if it is present in the source code. */
417415 Location getLocation ( ) {
418- result = this .asSourceCallable ( ) .getLocation ( ) or result = this .asClassHarness ( ) .getLocation ( )
416+ result = this .asSourceCallable ( ) .getLocation ( )
417+ or
418+ exists ( AstNode node |
419+ this .isGenericSynthesizedCallable ( node , _) and
420+ result = node .getLocation ( )
421+ )
419422 }
420423
421424 /** Gets the corresponding `StmtContainer` if this is a source callable. */
422425 StmtContainer asSourceCallable ( ) { this = MkSourceCallable ( result ) }
423426
424427 /** Gets the class constructor for which this is a class harness. */
425- Function asClassHarness ( ) { this = MkClassHarnessCallable ( result ) }
428+ predicate isGenericSynthesizedCallable ( AstNode node , string tag ) {
429+ this = MkGenericSynthesizedCallable ( node , tag )
430+ }
426431
427432 /** Gets the corresponding `StmtContainer` if this is a source callable. */
428433 pragma [ nomagic]
@@ -552,6 +557,8 @@ private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition
552557 n = TDynamicArgumentArrayNode ( invoke ) and
553558 pos .isDynamicArgumentArray ( )
554559 )
560+ or
561+ any ( AdditionalFlowInternal f ) .argument ( call , pos , n )
555562}
556563
557564predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) {
@@ -749,7 +756,7 @@ ContentApprox getContentApprox(Content c) {
749756}
750757
751758cached
752- private newtype TDataFlowCall =
759+ newtype TDataFlowCall =
753760 MkOrdinaryCall ( DataFlow:: InvokeNode node ) or
754761 MkPartialCall ( DataFlow:: PartialInvokeNode node , DataFlow:: Node callback ) {
755762 callback = node .getACallbackNode ( )
@@ -770,6 +777,9 @@ private newtype TDataFlowCall =
770777 FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
771778 ) {
772779 FlowSummaryImpl:: Private:: summaryCallbackRange ( c , receiver )
780+ } or
781+ MkGenericSynthesizedCall ( AstNode node , string tag , DataFlowCallable container ) {
782+ any ( AdditionalFlowInternal f ) .needsSynthesizedCall ( node , tag , container )
773783 }
774784
775785private module TotalOrdering {
@@ -835,6 +845,10 @@ class DataFlowCall extends TDataFlowCall {
835845 this = MkSummaryCall ( enclosingCallable , receiver )
836846 }
837847
848+ predicate isGenericSynthesizedCall ( AstNode node , string tag , DataFlowCallable container ) {
849+ this = MkGenericSynthesizedCall ( node , tag , container )
850+ }
851+
838852 Location getLocation ( ) { none ( ) } // Overridden in subclass
839853
840854 int totalorder ( ) {
@@ -953,6 +967,20 @@ private class ImpliedLambdaCall extends DataFlowCall, MkImpliedLambdaCall {
953967 }
954968}
955969
970+ class GenericSynthesizedCall extends DataFlowCall , MkGenericSynthesizedCall {
971+ private AstNode node ;
972+ private string tag ;
973+ private DataFlowCallable container ;
974+
975+ GenericSynthesizedCall ( ) { this = MkGenericSynthesizedCall ( node , tag , container ) }
976+
977+ override string toString ( ) { result = tag }
978+
979+ override Location getLocation ( ) { result = node .getLocation ( ) }
980+
981+ override DataFlowCallable getEnclosingCallable ( ) { result = container }
982+ }
983+
956984private int getMaxArity ( ) {
957985 // TODO: account for flow summaries
958986 result =
@@ -1050,6 +1078,8 @@ DataFlowCallable viableCallable(DataFlowCall node) {
10501078 )
10511079 or
10521080 result .asSourceCallableNotExterns ( ) = node .asImpliedLambdaCall ( )
1081+ or
1082+ any ( AdditionalFlowInternal f ) .viableCallable ( node , result )
10531083}
10541084
10551085/**
0 commit comments