Skip to content

Commit f340048

Browse files
gradle: parse slashy strings in pluginManagement scanner
1 parent a208888 commit f340048

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

gradle/lib/dependabot/gradle/file_fetcher/settings_file_parser.rb

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ def skip_quoted_string(content:, index:)
137137
def string_literal_at(content:, index:)
138138
return "'''" if content[index, 3] == "'''"
139139
return '"""' if content[index, 3] == '"""'
140+
return "$/" if content[index, 2] == "$/"
141+
return "/" if content[index, 1] == "/" && slashy_string_start?(content: content, index: index)
140142
return "'" if content[index, 1] == "'"
141143
return '"' if content[index, 1] == '"'
142144

@@ -145,6 +147,9 @@ def string_literal_at(content:, index:)
145147

146148
sig { params(content: String, start_index: Integer, quote: String).returns(Integer) }
147149
def advance_after_string(content:, start_index:, quote:)
150+
return advance_after_dollar_slashy_string(content: content, start_index: start_index) if quote == "$/"
151+
return advance_after_slashy_string(content: content, start_index: start_index) if quote == "/"
152+
148153
index = T.let(start_index, Integer)
149154

150155
while index < content.length
@@ -168,6 +173,67 @@ def advance_after_string(content:, start_index:, quote:)
168173
content.length
169174
end
170175

176+
sig { params(content: String, start_index: Integer).returns(Integer) }
177+
def advance_after_slashy_string(content:, start_index:)
178+
index = T.let(start_index, Integer)
179+
180+
while index < content.length
181+
if content[index, 1] == "\\"
182+
index += 2
183+
next
184+
end
185+
186+
return index + 1 if content[index, 1] == "/"
187+
188+
index += 1
189+
end
190+
191+
content.length
192+
end
193+
194+
sig { params(content: String, start_index: Integer).returns(Integer) }
195+
def advance_after_dollar_slashy_string(content:, start_index:)
196+
index = T.let(start_index, Integer)
197+
198+
while index < content.length
199+
return index + 2 if content[index, 2] == "/$"
200+
201+
if content[index, 1] == "$"
202+
index += 2
203+
next
204+
end
205+
206+
index += 1
207+
end
208+
209+
content.length
210+
end
211+
212+
sig { params(content: String, index: Integer).returns(T::Boolean) }
213+
def slashy_string_start?(content:, index:)
214+
return false if content[index, 2] == "//"
215+
return false if content[index, 2] == "/*"
216+
217+
previous = previous_non_whitespace_character(content: content, index: index)
218+
return true unless previous
219+
220+
!!(previous =~ /[=(:,!?&|\[{;]/)
221+
end
222+
223+
sig { params(content: String, index: Integer).returns(T.nilable(String)) }
224+
def previous_non_whitespace_character(content:, index:)
225+
cursor = T.let(index - 1, Integer)
226+
227+
while cursor >= 0
228+
character = T.must(content[cursor])
229+
return character unless character.match?(/\s/)
230+
231+
cursor -= 1
232+
end
233+
234+
nil
235+
end
236+
171237
sig { params(quote: String).returns(T::Boolean) }
172238
def triple_quote?(quote)
173239
quote.length == 3

gradle/spec/dependabot/gradle/file_fetcher/settings_file_parser_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,5 +223,43 @@
223223
expect(plugin_management_included_build_paths).to match_array(%w(build-logic))
224224
end
225225
end
226+
227+
context "when pluginManagement contains braces in slashy strings" do
228+
let(:settings_file_name) { "settings.gradle" }
229+
let(:settings_file) do
230+
Dependabot::DependencyFile.new(
231+
name: settings_file_name,
232+
content: <<~GROOVY
233+
pluginManagement {
234+
def marker = /}/
235+
includeBuild("build-logic")
236+
}
237+
GROOVY
238+
)
239+
end
240+
241+
it "ignores braces inside slashy strings" do
242+
expect(plugin_management_included_build_paths).to match_array(%w(build-logic))
243+
end
244+
end
245+
246+
context "when pluginManagement contains braces in dollar-slashy strings" do
247+
let(:settings_file_name) { "settings.gradle" }
248+
let(:settings_file) do
249+
Dependabot::DependencyFile.new(
250+
name: settings_file_name,
251+
content: <<~GROOVY
252+
pluginManagement {
253+
def marker = $/}/$
254+
includeBuild("build-logic")
255+
}
256+
GROOVY
257+
)
258+
end
259+
260+
it "ignores braces inside dollar-slashy strings" do
261+
expect(plugin_management_included_build_paths).to match_array(%w(build-logic))
262+
end
263+
end
226264
end
227265
end

0 commit comments

Comments
 (0)