50 lines
2 KiB
Diff
50 lines
2 KiB
Diff
# UNDF: UNDF-2026-000000093
|
||
Fixes grape-0003: Grape::DSL::Routing#route — endpoints Array#any? duplicate-check on every route registration O(N²).
|
||
|
||
--- a/lib/grape/dsl/routing.rb
|
||
+++ b/lib/grape/dsl/routing.rb
|
||
|
||
@@ DEFECT grape-0003: line 176 route method
|
||
|
||
def route(methods, paths = ['/'], route_options = {}, &)
|
||
...
|
||
new_endpoint = Grape::Endpoint.new(...)
|
||
- endpoints << new_endpoint unless endpoints.any? { |e| e.equals?(new_endpoint) }
|
||
+ endpoints << new_endpoint unless endpoints_set.include_equivalent?(new_endpoint)
|
||
...
|
||
end
|
||
|
||
# Simpler fix — use a separate tracking Hash keyed by endpoint identity:
|
||
|
||
@@ Preferred fix: track endpoint identity in a Hash alongside the Array
|
||
|
||
def reset_endpoints!
|
||
@endpoints = []
|
||
+ @endpoints_seen = {} # FIX: identity map for O(1) duplicate detection
|
||
end
|
||
|
||
def route(methods, paths = ['/'], route_options = {}, &)
|
||
...
|
||
new_endpoint = Grape::Endpoint.new(...)
|
||
+ key = new_endpoint.identity_key # endpoint must expose a stable identity string
|
||
- endpoints << new_endpoint unless endpoints.any? { |e| e.equals?(new_endpoint) }
|
||
+ unless @endpoints_seen.key?(key)
|
||
+ @endpoints_seen[key] = true
|
||
+ endpoints << new_endpoint
|
||
+ end
|
||
...
|
||
end
|
||
|
||
# BEFORE: endpoints is Array (initialized as @endpoints = [] in reset_endpoints!)
|
||
# On each call to route(), endpoints.any? { |e| e.equals?(new_endpoint) } scans all
|
||
# existing endpoints. With N routes registered: 1+2+3+...+N = O(N²/2) total checks.
|
||
#
|
||
# AFTER: Track seen endpoints in a Hash; Hash#key? is O(1)
|
||
# Total registration cost: O(N)
|
||
#
|
||
# Severity: HIGH — triggered at application startup for every route defined in a Grape API
|
||
# A large Grape API with 500 routes: 125,000 → 500 ops during boot
|
||
# Directly slows cold-start / server reload time proportionally to route count²
|
||
#
|
||
# Speedup: ~N/2 × where N = total routes
|
||
# At N=500 routes: ~250x reduction in duplicate-check ops
|