1
1
PuppetLint . new_check ( :check_unsafe_interpolations ) do
2
2
COMMANDS = Array [ 'command' , 'onlyif' , 'unless' ]
3
+ INTERPOLATED_STRINGS = Array [ :DQPRE , :DQMID ]
3
4
def check
4
5
# Gather any exec commands' resources into an array
5
6
exec_resources = resource_indexes . map { |resource |
6
7
resource_parameters = resource [ :param_tokens ] . map ( &:value )
7
8
resource if resource [ :type ] . value == 'exec' && !( COMMANDS & resource_parameters ) . empty?
8
9
} . compact
9
10
10
- # Get title tokens with modified puppet lint function
11
- title_tokens_list = get_title_tokens
11
+ # Filter the list of titles returned by get_title_tokens for those contained in an exec
12
+ exec_title_tokens = get_title_tokens . select { |title |
13
+ title if title [ :resource_type ] . value == 'exec'
14
+ } . compact
12
15
13
16
# Iterate over title tokens and raise a warning if any are variables
14
- title_tokens_list [ :tokens ] . each do | token |
15
- if token . type == :VARIABLE
16
- notify_warning ( token )
17
+ unless exec_title_tokens . empty?
18
+ exec_title_tokens . each do | title |
19
+ check_unsafe_title ( title )
17
20
end
18
21
end
19
22
@@ -23,11 +26,18 @@ def check
23
26
end
24
27
end
25
28
26
- # Iterates over tokens in a command and raises a warning if an interpolated variable is found
29
+ # Iterate over the tokens in a title and raise a warning if an interpolated variable is found
30
+ def check_unsafe_title ( title )
31
+ title [ :tokens ] . each do |token |
32
+ notify_warning ( token . next_code_token ) if interpolated? ( token )
33
+ end
34
+ end
35
+
36
+ # Iterates over an exec resource and if a command, onlyif or unless paramter is found, it is checked for unsafe interpolations
27
37
def check_unsafe_interpolations ( command_resources )
28
38
command_resources [ :tokens ] . each do |token |
29
- # We are only interested in tokens from command onwards
30
- next unless token . type == :NAME
39
+ # Skip iteration if token isn't a command of type :NAME
40
+ next unless COMMANDS . include? ( token . value ) && token . type == :NAME
31
41
# Don't check the command if it is parameterised
32
42
next if parameterised? ( token )
33
43
@@ -54,9 +64,7 @@ def check_command(token)
54
64
# Iterate through tokens in command
55
65
while current_token . type != :NEWLINE
56
66
# Check if token is a varibale and if it is parameterised
57
- if current_token . type == :VARIABLE
58
- rule_violations . append ( current_token )
59
- end
67
+ rule_violations . append ( current_token . next_code_token ) if interpolated? ( current_token )
60
68
current_token = current_token . next_token
61
69
end
62
70
@@ -76,45 +84,48 @@ def parameterised?(token)
76
84
# This function is a replacement for puppet_lint's title_tokens function which assumes titles have single quotes
77
85
# This function adds a check for titles in double quotes where there could be interpolated variables
78
86
def get_title_tokens
79
- tokens_array = [ ]
80
- result = { }
87
+ result = [ ]
81
88
tokens . each_index do |token_idx |
82
- if tokens [ token_idx ] . type == :COLON
83
- # Check if title is an array
84
- if tokens [ token_idx - 1 ] . type == :RBRACK
85
- array_start_idx = tokens . rindex do |r |
86
- r . type == :LBRACK
87
- end
88
- title_array_tokens = tokens [ ( array_start_idx + 1 ) ..( token_idx - 2 ) ]
89
- tokens_array . concat ( title_array_tokens . select do |token |
90
- { STRING : true , NAME : true } . include? ( token . type )
91
- end )
92
- result = {
93
- tokens : tokens_array ,
94
- resource_type : tokens [ array_start_idx ] . prev_code_token . prev_code_token
95
- }
96
- # Check if title is double quotes string
97
- elsif tokens [ token_idx - 1 ] . type == :DQPOST
98
- # Find index of the start of the title
99
- title_start_idx = tokens . rindex do |r |
100
- r . type == :DQPRE
101
- end
102
- result = {
103
- # Title is tokens from :DQPRE to the index before :COLON
104
- tokens : tokens [ title_start_idx ..( token_idx - 1 ) ] ,
105
- resource_type : tokens [ title_start_idx ] . prev_code_token . prev_code_token
106
- }
107
- # Title is in single quotes
108
- else
109
- next_token = tokens [ token_idx ] . next_code_token
110
- tokens_array . concat ( tokens [ ..token_idx - 1 ] ) unless next_token . type == :LBRACE
111
- result = {
112
- tokens : tokens_array ,
113
- resource_type : tokens [ token_idx - 1 ] . prev_code_token . prev_code_token
114
- }
89
+ next unless tokens [ token_idx ] . type == :COLON
90
+ tokens_array = [ ]
91
+ # Check if title is an array
92
+ if tokens [ token_idx - 1 ] . type == :RBRACK
93
+ array_start_idx = tokens . rindex do |r |
94
+ r . type == :LBRACK
95
+ end
96
+ title_array_tokens = tokens [ ( array_start_idx + 1 ) ..( token_idx - 2 ) ]
97
+ tokens_array . concat ( title_array_tokens . select do |token |
98
+ { STRING : true , NAME : true } . include? ( token . type )
99
+ end )
100
+ result << {
101
+ tokens : tokens_array ,
102
+ resource_type : tokens [ array_start_idx ] . prev_code_token . prev_code_token
103
+ }
104
+ # Check if title is double quotes string
105
+ elsif tokens [ token_idx - 1 ] . type == :DQPOST
106
+ # Find index of the start of the title
107
+ title_start_idx = tokens . rindex do |r |
108
+ r . type == :DQPRE
115
109
end
110
+ result << {
111
+ # Title is tokens from :DQPRE to the index before :COLON
112
+ tokens : tokens [ title_start_idx ..( token_idx - 1 ) ] ,
113
+ resource_type : tokens [ title_start_idx ] . prev_code_token . prev_code_token
114
+ }
115
+ # Title is in single quotes
116
+ else
117
+ next_token = tokens [ token_idx ] . next_code_token
118
+ tokens_array . concat ( [ tokens [ token_idx - 1 ] ] ) unless next_token . type == :LBRACE
119
+ result << {
120
+ tokens : tokens_array ,
121
+ resource_type : tokens [ token_idx - 1 ] . prev_code_token . prev_code_token
122
+ }
116
123
end
117
124
end
118
125
result
119
126
end
127
+
128
+ def interpolated? ( token )
129
+ INTERPOLATED_STRINGS . include? ( token . type )
130
+ end
120
131
end
0 commit comments