@@ -97,65 +97,50 @@ module Execa {
97
97
}
98
98
99
99
/**
100
- * A call to `execa.$` or `execa.$.sync` tag functions
100
+ * A call to `execa.$` or `execa.$.sync` or `execa.$({})` or `execa.$.sync({})` tag functions
101
101
*/
102
- private class ExecaScriptExpr extends DataFlow :: ExprNode {
102
+ private class ExecaScriptCall extends API :: CallNode {
103
103
boolean isSync ;
104
104
105
- ExecaScriptExpr ( ) {
106
- this . asExpr ( ) =
107
- [
108
- API :: moduleImport ( "execa" ) . getMember ( "$" ) ,
109
- API:: moduleImport ( "execa" ) .getMember ( "$" ) . getReturn ( )
110
- ] . getAValueReachableFromSource ( ) . asExpr ( ) and
111
- isSync = false
112
- or
113
- this . asExpr ( ) =
114
- [
115
- API :: moduleImport ( "execa" ) . getMember ( "$" ) . getMember ( "sync" ) ,
116
- API :: moduleImport ( "execa" ) .getMember ( "$" ) . getMember ( " sync") .getReturn ( )
117
- ] . getAValueReachableFromSource ( ) . asExpr ( ) and
118
- isSync = true
105
+ ExecaScriptCall ( ) {
106
+ exists ( API :: Node script |
107
+ script =
108
+ [
109
+ API:: moduleImport ( "execa" ) .getMember ( "$" ) ,
110
+ API :: moduleImport ( "execa" ) . getMember ( "$" ) . getReturn ( )
111
+ ]
112
+ |
113
+ this = script . getACall ( ) and
114
+ isSync = false
115
+ or
116
+ this = script .getMember ( "sync" ) .getACall ( ) and
117
+ isSync = true
118
+ )
119
119
}
120
120
}
121
121
122
+ API:: Node test ( ) { result = API:: moduleImport ( "execa" ) .getMember ( "$" ) .getASuccessor * ( ) }
123
+
122
124
/**
123
125
* The system command execution nodes for `execa.$` or `execa.$.sync` tag functions
124
126
*/
125
- class ExecaScriptEec extends SystemCommandExecution , ExecaScriptExpr {
126
- ExecaScriptEec ( ) { isSync = [ false , true ] }
127
+ class ExecaScript extends SystemCommandExecution , ExecaScriptCall {
128
+ ExecaScript ( ) { isSync = [ false , true ] }
127
129
128
- override DataFlow:: Node getACommandArgument ( ) {
129
- exists ( TemplateLiteral tl | isFirstTaggedTemplateParameter ( this .asExpr ( ) , tl ) |
130
- result .asExpr ( ) = tl .getChildExpr ( 0 ) and
131
- not result .asExpr ( ) .mayHaveStringValue ( " " ) // exclude whitespace
132
- )
133
- }
130
+ override DataFlow:: Node getACommandArgument ( ) { result = this .getParameter ( 1 ) .asSink ( ) }
134
131
135
132
override predicate isShellInterpreted ( DataFlow:: Node arg ) {
136
- // $({shell: true})`${cmd} ${arg0} ... ${arg1}`
137
- // ISSUE: $`cmd args` I can't reach the tag function argument easily
138
- exists ( TemplateLiteral tmpL | isFirstTaggedTemplateParameter ( this .asExpr ( ) , tmpL ) |
139
- arg .asExpr ( ) = tmpL .getAChildExpr ( ) and
140
- isExecaShellEnableWithExpr ( this .asExpr ( ) .( CallExpr ) .getArgument ( 0 ) ) and
141
- not arg .asExpr ( ) .mayHaveStringValue ( " " ) // exclude whitespace
142
- )
133
+ isExecaShellEnable ( this .getParameter ( 0 ) ) and
134
+ arg = this .getParameter ( 0 ) .asSink ( )
143
135
}
144
136
145
137
override DataFlow:: Node getArgumentList ( ) {
146
- // $`${cmd} ${arg0} ... ${argn}`
147
- exists ( TemplateLiteral tmpL | isFirstTaggedTemplateParameter ( this .asExpr ( ) , tmpL ) |
148
- result .asExpr ( ) = tmpL .getAChildExpr ( ) and
149
- not result .asExpr ( ) = tmpL .getChildExpr ( 0 ) and
150
- not result .asExpr ( ) .mayHaveStringValue ( " " ) // exclude whitespace
151
- )
138
+ result = this .getParameter ( any ( int i | i > 1 ) ) .asSink ( )
152
139
}
153
140
154
141
override predicate isSync ( ) { isSync = true }
155
142
156
- override DataFlow:: Node getOptionsArg ( ) {
157
- result = this .asExpr ( ) .getAChildExpr ( ) .flow ( ) and result .asExpr ( ) instanceof ObjectExpr
158
- }
143
+ override DataFlow:: Node getOptionsArg ( ) { result = this .getParameter ( 0 ) .asSink ( ) }
159
144
}
160
145
161
146
/**
@@ -207,28 +192,11 @@ module Execa {
207
192
}
208
193
}
209
194
210
- // Holds if left parameter is the left child of a template literal and returns the template literal
211
- private predicate isFirstTaggedTemplateParameter ( Expr left , TemplateLiteral templateLiteral ) {
212
- exists ( TaggedTemplateExpr parent |
213
- templateLiteral = parent .getTemplate ( ) and
214
- left = parent .getChildExpr ( 0 )
215
- )
216
- }
217
-
218
195
/**
219
196
* Holds whether Execa has shell enabled options or not, get Parameter responsible for options
220
197
*/
221
198
pragma [ inline]
222
199
private predicate isExecaShellEnable ( API:: Node n ) {
223
200
n .getMember ( "shell" ) .asSink ( ) .asExpr ( ) .( BooleanLiteral ) .getValue ( ) = "true"
224
201
}
225
-
226
- // Holds whether Execa has shell enabled options or not, get Parameter responsible for options
227
- private predicate isExecaShellEnableWithExpr ( Expr n ) {
228
- exists ( ObjectExpr o , Property p | o = n .getAChildExpr * ( ) |
229
- o .getAChild ( ) = p and
230
- p .getAChild ( ) .( Label ) .getName ( ) = "shell" and
231
- p .getAChild ( ) .( Literal ) .getValue ( ) = "true"
232
- )
233
- }
234
202
}
0 commit comments