@@ -97,65 +97,50 @@ module Execa {
9797 }
9898
9999 /**
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
101101 */
102- private class ExecaScriptExpr extends DataFlow :: ExprNode {
102+ private class ExecaScriptCall extends API :: CallNode {
103103 boolean isSync ;
104104
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+ )
119119 }
120120 }
121121
122+ API:: Node test ( ) { result = API:: moduleImport ( "execa" ) .getMember ( "$" ) .getASuccessor * ( ) }
123+
122124 /**
123125 * The system command execution nodes for `execa.$` or `execa.$.sync` tag functions
124126 */
125- class ExecaScriptEec extends SystemCommandExecution , ExecaScriptExpr {
126- ExecaScriptEec ( ) { isSync = [ false , true ] }
127+ class ExecaScript extends SystemCommandExecution , ExecaScriptCall {
128+ ExecaScript ( ) { isSync = [ false , true ] }
127129
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 ( ) }
134131
135132 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 ( )
143135 }
144136
145137 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 ( )
152139 }
153140
154141 override predicate isSync ( ) { isSync = true }
155142
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 ( ) }
159144 }
160145
161146 /**
@@ -207,28 +192,11 @@ module Execa {
207192 }
208193 }
209194
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-
218195 /**
219196 * Holds whether Execa has shell enabled options or not, get Parameter responsible for options
220197 */
221198 pragma [ inline]
222199 private predicate isExecaShellEnable ( API:: Node n ) {
223200 n .getMember ( "shell" ) .asSink ( ) .asExpr ( ) .( BooleanLiteral ) .getValue ( ) = "true"
224201 }
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- }
234202}
0 commit comments