From d48d7d2759a14067c0084e218d2251cfc27c9897 Mon Sep 17 00:00:00 2001 From: Garrett O'Reilly <10711685+goreilly@users.noreply.github.com> Date: Mon, 21 Oct 2019 13:21:52 -0700 Subject: [PATCH 1/2] Handle encoding frozen strings --- lib/attr_encrypted.rb | 7 ++++--- test/attr_encrypted_test.rb | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/attr_encrypted.rb b/lib/attr_encrypted.rb index 88e5f65e..ba466365 100644 --- a/lib/attr_encrypted.rb +++ b/lib/attr_encrypted.rb @@ -241,12 +241,13 @@ def decrypt(attribute, encrypted_value, options = {}) encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode] value = options[:encryptor].send(options[:decrypt_method], options.merge!(value: encrypted_value)) if options[:marshal] - value = options[:marshaler].send(options[:load_method], value) + options[:marshaler].send(options[:load_method], value) elsif defined?(Encoding) encoding = Encoding.default_internal || Encoding.default_external - value = value.force_encoding(encoding.name) + value.encode(encoding.name).freeze + else + value end - value else encrypted_value end diff --git a/test/attr_encrypted_test.rb b/test/attr_encrypted_test.rb index 84cb130a..9c65392f 100644 --- a/test/attr_encrypted_test.rb +++ b/test/attr_encrypted_test.rb @@ -374,6 +374,12 @@ def test_should_not_generate_salt_per_attribute_by_default assert_nil thing.encrypted_email_salt end + def test_should_decrypt_and_encode_frozen_strings + email = 'hello@example.com'.encode(Encoding::EUC_JP).freeze + @user = User.new(email: email) + assert_equal email, @user.decrypt(:email, @user.encrypted_email) + end + def test_should_decrypt_second_record @user1 = User.new @user1.email = 'test@example.com' From 90929f5293792c8aff6e2b6db199ab0d75fe3764 Mon Sep 17 00:00:00 2001 From: Garrett O'Reilly <10711685+goreilly@users.noreply.github.com> Date: Mon, 21 Oct 2019 14:49:03 -0700 Subject: [PATCH 2/2] smaller change, keep same behavior --- lib/attr_encrypted.rb | 2 +- test/attr_encrypted_test.rb | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/attr_encrypted.rb b/lib/attr_encrypted.rb index ba466365..25fef4f0 100644 --- a/lib/attr_encrypted.rb +++ b/lib/attr_encrypted.rb @@ -244,7 +244,7 @@ def decrypt(attribute, encrypted_value, options = {}) options[:marshaler].send(options[:load_method], value) elsif defined?(Encoding) encoding = Encoding.default_internal || Encoding.default_external - value.encode(encoding.name).freeze + value.dup.force_encoding(encoding.name) else value end diff --git a/test/attr_encrypted_test.rb b/test/attr_encrypted_test.rb index 9c65392f..b54ad857 100644 --- a/test/attr_encrypted_test.rb +++ b/test/attr_encrypted_test.rb @@ -13,6 +13,16 @@ def self.silly_decrypt(options) end end +class FreezingDecryptor + def self.frozen_encrypt(options) + options[:value].freeze + end + + def self.frozen_decrypt(options) + options[:value].freeze + end +end + class User extend AttrEncrypted self.attr_encrypted_options[:key] = Proc.new { |user| SECRET_KEY } # default key @@ -22,6 +32,7 @@ class User attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test' attr_encrypted :ssn, :key => :secret_key, :attribute => 'ssn_encrypted' attr_encrypted :credit_card, :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt, :some_arg => 'test' + attr_encrypted :frozen_string, :encryptor => FreezingDecryptor, :encrypt_method => :frozen_encrypt, :decrypt_method => :frozen_decrypt attr_encrypted :with_encoding, :key => SECRET_KEY, :encode => true attr_encrypted :with_custom_encoding, :key => SECRET_KEY, :encode => 'm' attr_encrypted :with_marshaling, :key => SECRET_KEY, :marshal => true @@ -37,7 +48,8 @@ class User attr_accessor :salt attr_accessor :should_encrypt - def initialize(email: nil) + def initialize(email: nil, frozen_string: nil) + self.frozen_string = frozen_string self.email = email self.salt = Time.now.to_i.to_s self.should_encrypt = true @@ -375,9 +387,9 @@ def test_should_not_generate_salt_per_attribute_by_default end def test_should_decrypt_and_encode_frozen_strings - email = 'hello@example.com'.encode(Encoding::EUC_JP).freeze - @user = User.new(email: email) - assert_equal email, @user.decrypt(:email, @user.encrypted_email) + user = User.new(frozen_string: 'test') + result = user.decrypt(:frozen_string, user.encrypted_frozen_string) + assert_equal 'test', result end def test_should_decrypt_second_record