@@ -13,6 +13,7 @@ private import sharedlib.FlowSummaryImpl as FlowSummaryImpl
13
13
private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate
14
14
private import semmle.javascript.dataflow.FlowSummary as FlowSummary
15
15
private import semmle.javascript.dataflow.internal.BarrierGuards
16
+ private import codeql.util.Boolean
16
17
17
18
class DataFlowSecondLevelScope = Unit ;
18
19
@@ -381,6 +382,8 @@ predicate postUpdatePair(Node pre, Node post) {
381
382
pre .( FlowSummaryNode ) .getSummaryNode ( ) )
382
383
or
383
384
VariableCaptureOutput:: capturePostUpdateNode ( getClosureNode ( post ) , getClosureNode ( pre ) )
385
+ or
386
+ any ( AdditionalFlowInternal f ) .postUpdate ( pre , post )
384
387
}
385
388
386
389
class CastNode extends DataFlow:: Node {
@@ -391,17 +394,12 @@ cached
391
394
newtype TDataFlowCallable =
392
395
MkSourceCallable ( StmtContainer container ) or
393
396
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 )
401
399
}
402
400
403
401
/**
404
- * A callable entity. This is a wrapper around either a `StmtContainer` or a `LibraryCallable`.
402
+ * A callable entity.
405
403
*/
406
404
class DataFlowCallable extends TDataFlowCallable {
407
405
/** Gets a string representation of this callable. */
@@ -410,19 +408,26 @@ class DataFlowCallable extends TDataFlowCallable {
410
408
or
411
409
result = this .asLibraryCallable ( )
412
410
or
413
- result = this .asClassHarness ( ) . toString ( )
411
+ this .isGenericSynthesizedCallable ( _ , result )
414
412
}
415
413
416
414
/** Gets the location of this callable, if it is present in the source code. */
417
415
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
+ )
419
422
}
420
423
421
424
/** Gets the corresponding `StmtContainer` if this is a source callable. */
422
425
StmtContainer asSourceCallable ( ) { this = MkSourceCallable ( result ) }
423
426
424
427
/** 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
+ }
426
431
427
432
/** Gets the corresponding `StmtContainer` if this is a source callable. */
428
433
pragma [ nomagic]
@@ -552,6 +557,8 @@ private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition
552
557
n = TDynamicArgumentArrayNode ( invoke ) and
553
558
pos .isDynamicArgumentArray ( )
554
559
)
560
+ or
561
+ any ( AdditionalFlowInternal f ) .argument ( call , pos , n )
555
562
}
556
563
557
564
predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) {
@@ -749,7 +756,7 @@ ContentApprox getContentApprox(Content c) {
749
756
}
750
757
751
758
cached
752
- private newtype TDataFlowCall =
759
+ newtype TDataFlowCall =
753
760
MkOrdinaryCall ( DataFlow:: InvokeNode node ) or
754
761
MkPartialCall ( DataFlow:: PartialInvokeNode node , DataFlow:: Node callback ) {
755
762
callback = node .getACallbackNode ( )
@@ -770,6 +777,9 @@ private newtype TDataFlowCall =
770
777
FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
771
778
) {
772
779
FlowSummaryImpl:: Private:: summaryCallbackRange ( c , receiver )
780
+ } or
781
+ MkGenericSynthesizedCall ( AstNode node , string tag , DataFlowCallable container ) {
782
+ any ( AdditionalFlowInternal f ) .needsSynthesizedCall ( node , tag , container )
773
783
}
774
784
775
785
private module TotalOrdering {
@@ -835,6 +845,10 @@ class DataFlowCall extends TDataFlowCall {
835
845
this = MkSummaryCall ( enclosingCallable , receiver )
836
846
}
837
847
848
+ predicate isGenericSynthesizedCall ( AstNode node , string tag , DataFlowCallable container ) {
849
+ this = MkGenericSynthesizedCall ( node , tag , container )
850
+ }
851
+
838
852
Location getLocation ( ) { none ( ) } // Overridden in subclass
839
853
840
854
int totalorder ( ) {
@@ -953,6 +967,20 @@ private class ImpliedLambdaCall extends DataFlowCall, MkImpliedLambdaCall {
953
967
}
954
968
}
955
969
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
+
956
984
private int getMaxArity ( ) {
957
985
// TODO: account for flow summaries
958
986
result =
@@ -1050,6 +1078,8 @@ DataFlowCallable viableCallable(DataFlowCall node) {
1050
1078
)
1051
1079
or
1052
1080
result .asSourceCallableNotExterns ( ) = node .asImpliedLambdaCall ( )
1081
+ or
1082
+ any ( AdditionalFlowInternal f ) .viableCallable ( node , result )
1053
1083
}
1054
1084
1055
1085
/**
0 commit comments