@@ -58,6 +58,9 @@ module Execa {
58
58
or
59
59
this = API:: moduleImport ( "execa" ) .getMember ( "execaSync" ) .getACall ( ) and
60
60
isSync = true
61
+ or
62
+ this = API:: moduleImport ( "execa" ) .getACall ( ) and
63
+ isSync = false
61
64
}
62
65
}
63
66
@@ -208,4 +211,86 @@ module Execa {
208
211
private predicate isExecaShellEnable ( API:: Node n ) {
209
212
n .getMember ( "shell" ) .asSink ( ) .asExpr ( ) .( BooleanLiteral ) .getValue ( ) = "true"
210
213
}
214
+
215
+ /**
216
+ * A call to `execa.node`
217
+ */
218
+ class ExecaNodeCall extends SystemCommandExecution , API:: CallNode {
219
+ ExecaNodeCall ( ) { this = API:: moduleImport ( "execa" ) .getMember ( "node" ) .getACall ( ) }
220
+
221
+ override DataFlow:: Node getACommandArgument ( ) { result = this .getArgument ( 0 ) }
222
+
223
+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { none ( ) }
224
+
225
+ override DataFlow:: Node getArgumentList ( ) {
226
+ result = this .getArgument ( 1 ) and
227
+ not result .asExpr ( ) instanceof ObjectExpr
228
+ }
229
+
230
+ override predicate isSync ( ) { none ( ) }
231
+
232
+ override DataFlow:: Node getOptionsArg ( ) {
233
+ result = this .getLastArgument ( ) and
234
+ result .asExpr ( ) instanceof ObjectExpr
235
+ }
236
+ }
237
+
238
+ /**
239
+ * A call to `execa.stdout`, `execa.stderr`, or `execa.sync`
240
+ */
241
+ class ExecaStreamCall extends SystemCommandExecution , API:: CallNode {
242
+ string methodName ;
243
+
244
+ ExecaStreamCall ( ) {
245
+ methodName in [ "stdout" , "stderr" , "sync" ] and
246
+ this = API:: moduleImport ( "execa" ) .getMember ( methodName ) .getACall ( )
247
+ }
248
+
249
+ override DataFlow:: Node getACommandArgument ( ) { result = this .getArgument ( 0 ) }
250
+
251
+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
252
+ arg = this .getArgument ( 0 ) and
253
+ isExecaShellEnable ( this .getParameter ( [ 1 , 2 ] ) )
254
+ }
255
+
256
+ override DataFlow:: Node getArgumentList ( ) {
257
+ result = this .getArgument ( 1 ) and
258
+ not result .asExpr ( ) instanceof ObjectExpr
259
+ }
260
+
261
+ override predicate isSync ( ) { methodName = "sync" }
262
+
263
+ override DataFlow:: Node getOptionsArg ( ) {
264
+ result = this .getLastArgument ( ) and
265
+ result .asExpr ( ) instanceof ObjectExpr
266
+ }
267
+ }
268
+
269
+ /**
270
+ * A call to `execa.shell` or `execa.shellSync`
271
+ */
272
+ class ExecaShellCall extends SystemCommandExecution , API:: CallNode {
273
+ boolean sync ;
274
+
275
+ ExecaShellCall ( ) {
276
+ this = API:: moduleImport ( "execa" ) .getMember ( "shell" ) .getACall ( ) and
277
+ sync = false
278
+ or
279
+ this = API:: moduleImport ( "execa" ) .getMember ( "shellSync" ) .getACall ( ) and
280
+ sync = true
281
+ }
282
+
283
+ override DataFlow:: Node getACommandArgument ( ) { result = this .getArgument ( 0 ) }
284
+
285
+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getACommandArgument ( ) }
286
+
287
+ override DataFlow:: Node getArgumentList ( ) { none ( ) }
288
+
289
+ override predicate isSync ( ) { sync = true }
290
+
291
+ override DataFlow:: Node getOptionsArg ( ) {
292
+ result = this .getArgument ( 1 ) and
293
+ result .asExpr ( ) instanceof ObjectExpr
294
+ }
295
+ }
211
296
}
0 commit comments