@@ -45,3 +45,57 @@ module Q {
4545 override DataFlow:: FunctionNode getExecutor ( ) { result = getCallback ( 0 ) }
4646 }
4747}
48+
49+ private module ClosurePromise {
50+ /**
51+ * A promise created by a call `new goog.Promise(executor)`.
52+ */
53+ private class ClosurePromiseDefinition extends PromiseDefinition , DataFlow:: NewNode {
54+ ClosurePromiseDefinition ( ) { this = Closure:: moduleImport ( "goog.Promise" ) .getACall ( ) }
55+
56+ override DataFlow:: FunctionNode getExecutor ( ) { result = getCallback ( 0 ) }
57+ }
58+
59+ /**
60+ * A promise created by a call `goog.Promise.resolve(value)`.
61+ */
62+ private class ResolvedClosurePromiseDefinition extends ResolvedPromiseDefinition {
63+ ResolvedClosurePromiseDefinition ( ) {
64+ this = Closure:: moduleImport ( "goog.Promise.resolve" ) .getACall ( )
65+ }
66+
67+ override DataFlow:: Node getValue ( ) { result = getArgument ( 0 ) }
68+ }
69+
70+ /**
71+ * Taint steps through closure promise methods.
72+ */
73+ private class ClosurePromiseTaintStep extends TaintTracking:: AdditionalTaintStep {
74+ DataFlow:: Node pred ;
75+
76+ ClosurePromiseTaintStep ( ) {
77+ // static methods in goog.Promise
78+ exists ( DataFlow:: CallNode call , string name |
79+ call = Closure:: moduleImport ( "goog.Promise." + name ) .getACall ( ) and
80+ this = call and
81+ pred = call .getAnArgument ( )
82+ |
83+ name = "all" or
84+ name = "allSettled" or
85+ name = "firstFulfilled" or
86+ name = "race"
87+ )
88+ or
89+ // promise created through goog.promise.withResolver()
90+ exists ( DataFlow:: CallNode resolver |
91+ resolver = Closure:: moduleImport ( "goog.Promise.withResolver" ) .getACall ( ) and
92+ this = resolver .getAPropertyRead ( "promise" ) and
93+ pred = resolver .getAMethodCall ( "resolve" ) .getArgument ( 0 )
94+ )
95+ }
96+
97+ override predicate step ( DataFlow:: Node src , DataFlow:: Node dst ) {
98+ src = pred and dst = this
99+ }
100+ }
101+ }
0 commit comments