From 9010274627a538c688e44737e7a50c659da7e863 Mon Sep 17 00:00:00 2001 From: Adam Panzer Date: Tue, 10 Jun 2014 10:53:48 -0700 Subject: [PATCH] fix error with long keys in ActiveSupport::Cache::FileStore --- activesupport/CHANGELOG.md | 3 +++ activesupport/lib/active_support/cache/file_store.rb | 5 +++++ activesupport/test/caching_test.rb | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 871e1705f7..5962dd255c 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,6 @@ +* Fixed `ActiveSupport::Cache::FileStore` exploding with long paths. + *Adam Panzer / Michael Grosser* + * Fixed `ActiveSupport::TimeWithZone#-` so precision is not unnecessarily lost when working with objects with a nanosecond component. diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 8ed60aebac..d08ecd2f7d 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -14,6 +14,7 @@ module ActiveSupport DIR_FORMATTER = "%03X" FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) + FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room EXCLUDED_DIRS = ['.', '..'].freeze def initialize(cache_path, options = nil) @@ -117,6 +118,10 @@ module ActiveSupport # Translate a key into a file path. def key_file_path(key) + if key.size > FILEPATH_MAX_SIZE + key = Digest::MD5.hexdigest(key) + end + fname = URI.encode_www_form_component(key) hash = Zlib.adler32(fname) hash, dir_1 = hash.divmod(0x1000) diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 18923f61d1..d55cc5d3b0 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -692,6 +692,11 @@ class FileStoreTest < ActiveSupport::TestCase assert File.exist?(filepath) end + def test_long_keys + @cache.write("a"*10000, 1) + assert_equal 1, @cache.read("a"*10000) + end + def test_key_transformation key = @cache.send(:key_file_path, "views/index?id=1") assert_equal "views/index?id=1", @cache.send(:file_path_key, key)