@@ -8,29 +8,55 @@ class BashShellScript extends ShellScript {
88 )
99 }
1010
11- private string lineProducer ( int i ) {
12- result = this .getRawScript ( ) .regexpReplaceAll ( "\\\\\\s*\n" , "" ) .splitAt ( "\n" , i )
11+ /**
12+ * Gets the line at 0-based index `lineIndex` within this shell script,
13+ * assuming newlines as separators.
14+ */
15+ private string lineProducer ( int lineIndex ) {
16+ result = this .getRawScript ( ) .regexpReplaceAll ( "\\\\\\s*\n" , "" ) .splitAt ( "\n" , lineIndex )
1317 }
1418
15- private predicate cmdSubstitutionReplacement ( string cmdSubs , string id , int k ) {
16- exists ( string line | line = this .lineProducer ( k ) |
17- exists ( int i , int j |
18- cmdSubs =
19- // $() cmd substitution
20- line .regexpFind ( "\\$\\((?:[^()]+|\\((?:[^()]+|\\([^()]*\\))*\\))*\\)" , i , j )
21- .regexpReplaceAll ( "^\\$\\(" , "" )
22- .regexpReplaceAll ( "\\)$" , "" ) and
23- id = "cmdsubs:" + k + ":" + i + ":" + j
24- )
25- or
26- exists ( int i , int j |
27- // `...` cmd substitution
28- cmdSubs =
29- line .regexpFind ( "\\`[^\\`]+\\`" , i , j )
30- .regexpReplaceAll ( "^\\`" , "" )
31- .regexpReplaceAll ( "\\`$" , "" ) and
32- id = "cmd:" + k + ":" + i + ":" + j
33- )
19+ private predicate cmdSubstitutionReplacement ( string command , string id , int lineIndex ) {
20+ this .commandInSubstitution ( lineIndex , command , id )
21+ or
22+ this .commandInBackticks ( lineIndex , command , id )
23+ }
24+
25+ /**
26+ * Holds if there is a command substitution `$(command)` in
27+ * the line at `lineIndex` in the shell script,
28+ * and `id` is a unique identifier for this command.
29+ */
30+ private predicate commandInSubstitution ( int lineIndex , string command , string id ) {
31+ exists ( int occurrenceIndex , int occurrenceOffset |
32+ command =
33+ // Look for the command inside a $(...) command substitution
34+ this .lineProducer ( lineIndex )
35+ .regexpFind ( "\\$\\((?:[^()]+|\\((?:[^()]+|\\([^()]*\\))*\\))*\\)" , occurrenceIndex ,
36+ occurrenceOffset )
37+ // trim starting $( - TODO do this in first regex
38+ .regexpReplaceAll ( "^\\$\\(" , "" )
39+ // trim ending ) - TODO do this in first regex
40+ .regexpReplaceAll ( "\\)$" , "" ) and
41+ id = "cmdsubs:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset
42+ )
43+ }
44+
45+ /**
46+ * Holds if `command` is a command in backticks `` `...` `` in
47+ * the line at `lineIndex` in the shell script,
48+ * and `id` is a unique identifier for this command.
49+ */
50+ private predicate commandInBackticks ( int lineIndex , string command , string id ) {
51+ exists ( int occurrenceIndex , int occurrenceOffset |
52+ command =
53+ this .lineProducer ( lineIndex )
54+ .regexpFind ( "\\`[^\\`]+\\`" , occurrenceIndex , occurrenceOffset )
55+ // trim leading backtick - TODO do this in first regex
56+ .regexpReplaceAll ( "^\\`" , "" )
57+ // trim trailing backtick - TODO do this in first regex
58+ .regexpReplaceAll ( "\\`$" , "" ) and
59+ id = "cmd:" + lineIndex + ":" + occurrenceIndex + ":" + occurrenceOffset
3460 )
3561 }
3662
0 commit comments