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 {
544544 }
545545}
546546
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+
547566class ArrayCoercionPackage extends FunctionalPackageSummary {
548567 ArrayCoercionPackage ( ) { this = "ArrayCoercionPackage" }
549568
Original file line number Diff line number Diff line change @@ -49,3 +49,10 @@ string getAnArrayContent() {
4949 // Values stored at an unknown index
5050 result = "ArrayElement[?]"
5151}
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 {
368368 )
369369 }
370370}
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