File tree Expand file tree Collapse file tree 6 files changed +110
-0
lines changed
lib/semmle/javascript/internal/flow_summaries
test/library-tests/TripleDot Expand file tree Collapse file tree 6 files changed +110
-0
lines changed Original file line number Diff line number Diff line change @@ -544,6 +544,25 @@ class ToSpliced extends SummarizedCallable {
544
544
}
545
545
}
546
546
547
+ class With extends SummarizedCallable {
548
+ With ( ) { this = "Array#with" }
549
+
550
+ override InstanceCall getACallSimple ( ) { result .getMethodName ( ) = "with" }
551
+
552
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
553
+ preservesValue = true and
554
+ (
555
+ // Copy all elements from the original array to the new array
556
+ input = "Argument[this].WithArrayElement" and
557
+ output = "ReturnValue"
558
+ or
559
+ // Replace the value at the specified index
560
+ input = "Argument[1]" and
561
+ output = "ReturnValue.ArrayElement"
562
+ )
563
+ }
564
+ }
565
+
547
566
class ArrayCoercionPackage extends FunctionalPackageSummary {
548
567
ArrayCoercionPackage ( ) { this = "ArrayCoercionPackage" }
549
568
Original file line number Diff line number Diff line change @@ -49,3 +49,10 @@ string getAnArrayContent() {
49
49
// Values stored at an unknown index
50
50
result = "ArrayElement[?]"
51
51
}
52
+
53
+ /**
54
+ * Gets an argument position up to a certain limit.
55
+ *
56
+ * This can be used to generate flow summaries that should preserve such positions.
57
+ */
58
+ int getAnArgumentPosition ( ) { result = [ 0 .. 10 ] }
Original file line number Diff line number Diff line change @@ -368,3 +368,29 @@ private class PromiseWithResolversLike extends SummarizedCallable {
368
368
)
369
369
}
370
370
}
371
+
372
+ class PromiseTry extends DataFlow:: SummarizedCallable {
373
+ PromiseTry ( ) { this = "Promise.try()" }
374
+
375
+ override DataFlow:: CallNode getACallSimple ( ) {
376
+ result = promiseConstructorRef ( ) .getAMemberCall ( [ "try" , "attempt" ] )
377
+ or
378
+ result = DataFlow:: moduleImport ( [ "p-try" , "es6-promise-try" ] ) .getACall ( )
379
+ }
380
+
381
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
382
+ preservesValue = true and
383
+ (
384
+ exists ( int i | i = getAnArgumentPosition ( ) |
385
+ input = "Argument[" + ( i + 1 ) + "]" and
386
+ output = "Argument[0].Parameter[" + i + "]"
387
+ )
388
+ or
389
+ input = "Argument[0].ReturnValue" and
390
+ output = "ReturnValue.Awaited"
391
+ or
392
+ input = "Argument[0].ReturnValue[exception]" and
393
+ output = "ReturnValue.Awaited[error]"
394
+ )
395
+ }
396
+ }
Original file line number Diff line number Diff line change
1
+ ---
2
+ category : minorAnalysis
3
+ ---
4
+ * Data flow is now tracked through the ` Promise.try ` and ` Array.prototype.with ` functions.
Original file line number Diff line number Diff line change
1
+ function t1 ( ) {
2
+ const arr = [ 1 , 2 , 3 ] ;
3
+ const newArr = arr . with ( 1 , source ( 'with.1' ) ) ;
4
+ sink ( newArr [ 1 ] ) ; // $ hasValueFlow=with.1
5
+ }
6
+
7
+ function t2 ( ) {
8
+ const arr = [ source ( 'with.2.1' ) , 2 , source ( 'with.2.3' ) ] ;
9
+ const newArr = arr . with ( 1 , 'replaced' ) ;
10
+ sink ( newArr [ 0 ] ) ; // $ hasValueFlow=with.2.1
11
+ sink ( newArr [ 2 ] ) ; // $ hasValueFlow=with.2.3
12
+ }
13
+
14
+ function t3 ( ) {
15
+ const arr = [ 1 , 2 , 3 ] ;
16
+ const index = source ( 'with.3.index' ) ;
17
+ const newArr = arr . with ( index , 'new value' ) ;
18
+ // No assertions here as the index is tainted, not the value
19
+ }
20
+
21
+ function t4 ( ) {
22
+ const arr = [ 1 , 2 , 3 ] ;
23
+ const newArr = arr . with ( 1 , source ( 'with.4' ) ) ;
24
+ sink ( arr [ 1 ] ) ; // This should NOT have value flow as with() returns a new array
25
+ }
Original file line number Diff line number Diff line change
1
+ async function t1 ( ) {
2
+ const promise = Promise . try ( ( ) => {
3
+ return source ( 'try.1' ) ;
4
+ } ) ;
5
+ sink ( await promise ) ; // $ hasValueFlow=try.1
6
+ }
7
+
8
+ async function t2 ( ) {
9
+ const promise = Promise . try ( ( x ) => {
10
+ return x
11
+ } , source ( 'try.2' ) ) ;
12
+ sink ( await promise ) ; // $ hasValueFlow=try.2
13
+ }
14
+
15
+ async function t3 ( ) {
16
+ const promise = Promise . try ( ( x ) => {
17
+ throw x ;
18
+ } , source ( 'try.3' ) ) ;
19
+ promise . catch ( err => {
20
+ sink ( err ) ; // $ hasValueFlow=try.3
21
+ } ) ;
22
+ }
23
+
24
+ async function t4 ( ) {
25
+ const promise = Promise . try ( ( x , y ) => {
26
+ return y ;
27
+ } , source ( 'try.4.1' ) , source ( 'try.4.2' ) ) ;
28
+ sink ( await promise ) ; // $ hasValueFlow=try.4.2
29
+ }
You can’t perform that action at this time.
0 commit comments