@@ -15,7 +15,7 @@ module ShellJS {
1515 .getMember ( [
1616 "exec" , "cd" , "cp" , "touch" , "chmod" , "pushd" , "find" , "ls" , "ln" , "mkdir" , "mv" ,
1717 "rm" , "cat" , "head" , "sort" , "tail" , "uniq" , "grep" , "sed" , "to" , "toEnd" , "echo" ,
18- "which" ,
18+ "which" , "cmd" , "asyncExec"
1919 ] )
2020 .getReturn ( )
2121 }
@@ -154,16 +154,27 @@ module ShellJS {
154154 }
155155
156156 /**
157- * A call to `shelljs.exec()` modeled as command execution.
157+ * A call to `shelljs.exec()`, `shelljs.cmd()`, or `async-shelljs.asyncExec()` modeled as command execution.
158158 */
159159 private class ShellJSExec extends SystemCommandExecution , ShellJSCall {
160- ShellJSExec ( ) { name = "exec" }
161-
162- override DataFlow:: Node getACommandArgument ( ) { result = this .getArgument ( 0 ) }
160+ ShellJSExec ( ) { name = [ "exec" , "cmd" , "asyncExec" ] }
161+
162+ override DataFlow:: Node getACommandArgument ( ) {
163+ if name = "cmd"
164+ then
165+ result = this .getArgument ( _) and
166+ not (
167+ result = this .getLastArgument ( ) and
168+ exists ( this .getOptionsArg ( ) )
169+ )
170+ else
171+ // For exec/asyncExec: only first argument is command
172+ result = this .getArgument ( 0 )
173+ }
163174
164175 override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getACommandArgument ( ) }
165176
166- override predicate isSync ( ) { none ( ) }
177+ override predicate isSync ( ) { name = "cmd" }
167178
168179 override DataFlow:: Node getOptionsArg ( ) {
169180 result = this .getLastArgument ( ) and
0 commit comments