Skip to content

Commit

Permalink
[Fix rubocop#9492] Fix an incorrect auto-correct for `Lint/Deprecated…
Browse files Browse the repository at this point in the history
…OpenSSLConstant`

Fixes rubocop#9492.

This PR fixes an incorrect auto-correct for `Lint/DeprecatedOpenSSLConstant`
when using no argument algorithm.
  • Loading branch information
koic authored and bbatsov committed Feb 8, 2021
1 parent 21b6bfb commit f919444
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
@@ -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][])
17 changes: 13 additions & 4 deletions lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb
Expand Up @@ -44,6 +44,8 @@ class DeprecatedOpenSSLConstant < Base
MSG = 'Use `%<constant>s.%<method>s(%<replacement_args>s)`' \
' instead of `%<original>s`.'

NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze

def_node_matcher :algorithm_const, <<~PATTERN
(send
$(const
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
24 changes: 24 additions & 0 deletions spec/rubocop/cop/lint/deprecated_open_ssl_constant_spec.rb
Expand Up @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit f919444

Please sign in to comment.