diff --git a/changelog/fix_incorrect_autocorrect_for_lint_deprecated_open_ssl_constant.md b/changelog/fix_incorrect_autocorrect_for_lint_deprecated_open_ssl_constant.md new file mode 100644 index 00000000000..4dfab862e74 --- /dev/null +++ b/changelog/fix_incorrect_autocorrect_for_lint_deprecated_open_ssl_constant.md @@ -0,0 +1 @@ +* [#9492](https://github.com/rubocop-hq/rubocop/issues/9492): Fix an incorrect auto-correct for `Lint/DeprecatedOpenSSLConstant` when using no argument algorithm. ([@koic][]) diff --git a/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb b/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb index 16b7c4430a3..64a6a56e4d9 100644 --- a/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +++ b/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb @@ -44,6 +44,8 @@ class DeprecatedOpenSSLConstant < Base MSG = 'Use `%s.%s(%s)`' \ ' instead of `%s`.' + NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze + def_node_matcher :algorithm_const, <<~PATTERN (send $(const @@ -104,7 +106,7 @@ def openssl_class(node) def algorithm_name(node) name = node.loc.name.source - if openssl_class(node) == 'OpenSSL::Cipher' + if openssl_class(node) == 'OpenSSL::Cipher' && !NO_ARG_ALGORITHM.include?(name) name.scan(/.{3}/).join('-') else name @@ -124,16 +126,23 @@ def replacement_args(node) algorithm_name = algorithm_name(algorithm_constant) if openssl_class(algorithm_constant) == 'OpenSSL::Cipher' - build_cipher_arguments(node, algorithm_name) + build_cipher_arguments(node, algorithm_name, node.arguments.empty?) else (["'#{algorithm_name}'"] + node.arguments.map(&:source)).join(', ') end end - def build_cipher_arguments(node, algorithm_name) + def build_cipher_arguments(node, algorithm_name, no_arguments) algorithm_parts = algorithm_name.downcase.split('-') size_and_mode = sanitize_arguments(node.arguments).map(&:downcase) - "'#{(algorithm_parts + size_and_mode + ['cbc']).take(3).join('-')}'" + + if NO_ARG_ALGORITHM.include?(algorithm_parts.first.upcase) && no_arguments + "'#{algorithm_parts.first}'" + else + mode = 'cbc' unless size_and_mode == ['cbc'] + + "'#{(algorithm_parts + size_and_mode + [mode]).compact.take(3).join('-')}'" + end end end end diff --git a/spec/rubocop/cop/lint/deprecated_open_ssl_constant_spec.rb b/spec/rubocop/cop/lint/deprecated_open_ssl_constant_spec.rb index c53090863de..547b44d4b7f 100644 --- a/spec/rubocop/cop/lint/deprecated_open_ssl_constant_spec.rb +++ b/spec/rubocop/cop/lint/deprecated_open_ssl_constant_spec.rb @@ -34,6 +34,17 @@ RUBY end + it 'registers an offense with cipher constant and `cbc` argument and corrects' do + expect_offense(<<~RUBY) + OpenSSL::Cipher::DES.new('cbc') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `OpenSSL::Cipher.new('des-cbc')` instead of `OpenSSL::Cipher::DES.new('cbc')`. + RUBY + + expect_correction(<<~RUBY) + OpenSSL::Cipher.new('des-cbc') + RUBY + end + it 'registers an offense with AES + blocksize constant and mode argument and corrects' do expect_offense(<<~RUBY) OpenSSL::Cipher::AES128.new(:GCM) @@ -45,6 +56,19 @@ RUBY end + RuboCop::Cop::Lint::DeprecatedOpenSSLConstant::NO_ARG_ALGORITHM.each do |algorithm_name| + it 'registers an offense with cipher constant and no arguments and corrects' do + expect_offense(<<~RUBY, algorithm_name: algorithm_name) + OpenSSL::Cipher::#{algorithm_name}.new + ^^^^^^^^^^^^^^^^^^{algorithm_name}^^^^ Use `OpenSSL::Cipher.new('#{algorithm_name.downcase}')` instead of `OpenSSL::Cipher::#{algorithm_name}.new`. + RUBY + + expect_correction(<<~RUBY) + OpenSSL::Cipher.new('#{algorithm_name.downcase}') + RUBY + end + end + it 'registers an offense with AES + blocksize constant and corrects' do expect_offense(<<~RUBY) OpenSSL::Cipher::AES128.new