Skip to content

Commit 7ee9408

Browse files
committed
Land rapid7#7647, Search with an intersect instead of a union
2 parents f45b0e3 + 889de05 commit 7ee9408

File tree

1 file changed

+40
-81
lines changed

1 file changed

+40
-81
lines changed

lib/msf/core/db_manager/module_cache.rb

Lines changed: 40 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,7 @@ module Msf::DBManager::ModuleCache
2525
# @param values [Set<String>, #each] a list of strings.
2626
# @return [Arrray<String>] strings wrapped like %<string>%
2727
def match_values(values)
28-
wrapped_values = values.collect { |value|
29-
"%#{value}%"
30-
}
31-
32-
wrapped_values
28+
values.collect { |value| "%#{value}%" }
3329
end
3430

3531
def module_to_details_hash(m)
@@ -200,102 +196,65 @@ def search_modules(search_string)
200196
end
201197
end
202198

203-
query = Mdm::Module::Detail.all
204-
205199
ActiveRecord::Base.connection_pool.with_connection do
206-
# Although AREL supports taking the union or two queries, the ActiveRecord where syntax only supports
207-
# intersection, so creating the where clause has to be delayed until all conditions can be or'd together and
208-
# passed to one call ot where.
209-
union_conditions = []
210-
200+
@query = Mdm::Module::Detail.all
201+
202+
@archs = Set.new
203+
@authors = Set.new
204+
@names = Set.new
205+
@os = Set.new
206+
@refs = Set.new
207+
@stances = Set.new
208+
@text = Set.new
209+
@types = Set.new
210+
211211
value_set_by_keyword.each do |keyword, value_set|
212+
formatted_values = match_values(value_set)
213+
212214
case keyword
213-
when 'author'
214-
formatted_values = match_values(value_set)
215-
216-
query = query.includes(:authors).references(:authors)
217-
module_authors = Mdm::Module::Author.arel_table
218-
union_conditions << module_authors[:email].matches_any(formatted_values)
219-
union_conditions << module_authors[:name].matches_any(formatted_values)
220-
when 'name'
221-
formatted_values = match_values(value_set)
222-
223-
module_details = Mdm::Module::Detail.arel_table
224-
union_conditions << module_details[:fullname].matches_any(formatted_values)
225-
union_conditions << module_details[:name].matches_any(formatted_values)
226-
when 'os', 'platform'
227-
formatted_values = match_values(value_set)
228-
229-
query = query.includes(:platforms).references(:platforms)
230-
union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values)
231-
232-
query = query.includes(:targets).references(:targets)
233-
union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values)
234-
when 'text'
235-
formatted_values = match_values(value_set)
236-
237-
module_details = Mdm::Module::Detail.arel_table
238-
union_conditions << module_details[:description].matches_any(formatted_values)
239-
union_conditions << module_details[:fullname].matches_any(formatted_values)
240-
union_conditions << module_details[:name].matches_any(formatted_values)
241-
242-
query = query.includes(:actions).references(:actions)
243-
union_conditions << Mdm::Module::Action.arel_table[:name].matches_any(formatted_values)
244-
245-
query = query.includes(:archs).references(:archs)
246-
union_conditions << Mdm::Module::Arch.arel_table[:name].matches_any(formatted_values)
247-
248-
query = query.includes(:authors).references(:authors)
249-
union_conditions << Mdm::Module::Author.arel_table[:name].matches_any(formatted_values)
250-
251-
query = query.includes(:platforms).references(:platforms)
252-
union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values)
253-
254-
query = query.includes(:refs).references(:refs)
255-
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values)
256-
257-
query = query.includes(:targets).references(:targets)
258-
union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values)
259-
when 'type'
260-
formatted_values = match_values(value_set)
261-
union_conditions << Mdm::Module::Detail.arel_table[:mtype].matches_any(formatted_values)
262215
when 'app'
263216
formatted_values = value_set.collect { |value|
264217
formatted_value = 'aggressive'
265-
266218
if value == 'client'
267219
formatted_value = 'passive'
268220
end
269-
270221
formatted_value
271222
}
272-
273-
union_conditions << Mdm::Module::Detail.arel_table[:stance].eq_any(formatted_values)
223+
@stances << formatted_values
224+
when 'arch'
225+
@archs << formatted_values
226+
when 'author'
227+
@authors << formatted_values
228+
when 'name'
229+
@names << formatted_values
230+
when 'os', 'platform'
231+
@os << formatted_values
274232
when 'ref'
275-
formatted_values = match_values(value_set)
276-
277-
query = query.includes(:refs).references(:refs)
278-
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values)
233+
@refs << formatted_values
279234
when 'cve', 'bid', 'edb'
280235
formatted_values = value_set.collect { |value|
281236
prefix = keyword.upcase
282-
283237
"#{prefix}-%#{value}%"
284238
}
285-
286-
query = query.includes(:refs).references(:refs)
287-
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values)
239+
@refs << formatted_values
240+
when 'text'
241+
@text << formatted_values
242+
when 'type'
243+
@types << formatted_values
288244
end
289245
end
290-
291-
unioned_conditions = union_conditions.inject { |union, condition|
292-
union.or(condition)
293-
}
294-
295-
query = query.where(unioned_conditions).to_a.uniq { |m| m.fullname }
296246
end
297-
298-
query
247+
248+
@query = @query.module_arch( @archs.to_a.flatten ) if @archs.any?
249+
@query = @query.module_author( @authors.to_a.flatten ) if @authors.any?
250+
@query = @query.module_name( @names.to_a.flatten ) if @names.any?
251+
@query = @query.module_os_or_platform( @os.to_a.flatten ) if @os.any?
252+
@query = @query.module_text( @text.to_a.flatten ) if @text.any?
253+
@query = @query.module_type( @types.to_a.flatten ) if @types.any?
254+
@query = @query.module_stance( @stances.to_a.flatten ) if @stances.any?
255+
@query = @query.module_ref( @refs.to_a.flatten ) if @refs.any?
256+
257+
@query.uniq
299258
end
300259

301260
# Destroys the old Mdm::Module::Detail and creates a new Mdm::Module::Detail for

0 commit comments

Comments
 (0)