From 6af29fb44e5aac33a2cd74ba2daf75b242e6aef9 Mon Sep 17 00:00:00 2001 From: Gonzalo Rodriguez Date: Mon, 29 Jan 2018 12:19:05 -0300 Subject: [PATCH] Avoid 'defined?' buggy behavior in ruby 2.5.0. Fixes #253 'defined?' is buggy in ruby 2.5.0, which under certain circumstances users using rack-attack can hit. See issue #253. I reported (https://bugs.ruby-lang.org/issues/14407) and fixed (https://github.com/ruby/ruby/pull/1800) the issue in ruby already, but i guess i would take some time before there's a new ruby release including that fix. So for now we would need to circumvent this bug by using 'const_defined?' instead of 'defined?' for this particular case. More details: Anyone using: * ruby 2.5.0 * redis * rack-attack without redis-store and using at least one throttle * having a toplevel class named Store will hit this ruby 2.5.0 bug https://bugs.ruby-lang.org/issues/14407 That's because of the following buggy behavior of 'defined?' under ruby 2.5: ``` $ ruby -v ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux] $ irb > class Redis > end => nil > class Store > end => nil > defined?(::Redis::Store) => "constant" > ::Redis::Store NameError (uninitialized constant Redis::Store Did you mean? Store) ``` --- lib/rack/attack/store_proxy/redis_store_proxy.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/rack/attack/store_proxy/redis_store_proxy.rb b/lib/rack/attack/store_proxy/redis_store_proxy.rb index c980369..1a7c20a 100644 --- a/lib/rack/attack/store_proxy/redis_store_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_store_proxy.rb @@ -5,7 +5,14 @@ module Rack module StoreProxy class RedisStoreProxy < SimpleDelegator def self.handle?(store) - defined?(::Redis::Store) && store.is_a?(::Redis::Store) + # Using const_defined? for now. + # + # Go back to use defined? once this ruby issue is + # fixed and released: + # https://bugs.ruby-lang.org/issues/14407 + # + # defined?(::Redis::Store) && store.is_a?(::Redis::Store) + const_defined?("::Redis::Store") && store.is_a?(::Redis::Store) end def initialize(store)