@@ -58,6 +58,9 @@ module Execa {
5858 or
5959 this = API:: moduleImport ( "execa" ) .getMember ( "execaSync" ) .getACall ( ) and
6060 isSync = true
61+ or
62+ this = API:: moduleImport ( "execa" ) .getACall ( ) and
63+ isSync = false
6164 }
6265 }
6366
@@ -208,4 +211,86 @@ module Execa {
208211 private predicate isExecaShellEnable ( API:: Node n ) {
209212 n .getMember ( "shell" ) .asSink ( ) .asExpr ( ) .( BooleanLiteral ) .getValue ( ) = "true"
210213 }
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+ }
211296}
0 commit comments