🌊

[Bug #21662] 意図せず変数が書き換えられてしまうバグ報告

に公開

[Bug #21662] Variables other than those in the conditional score are replaced.

  • 以下のようなコードを実行した際に bar = ''bar.name まで書き換えてしまうというバグ報告
class Bar
  attr_accessor :name
end

class Foo
  attr_accessor :bar
  def initialize(bar=nil)
    @bar = bar || Bar.new
  end

  def bug!
    # Bar 以外の場合は bar = '' する
    # Bar の場合は if bar.name == 'bar' で更に条件分岐する
    if !bar.is_a?(Bar)
      bar = ''
    elsif bar.name == 'bar'
    end
  end
end

# error: undefined method 'name' for nil (NoMethodError)
Foo.new.bug!
  • 上記のコードを実行した場合、 barBar.new が割り当てられているので bar = '' の処理は呼ばれずに if bar.name の分岐処理が呼ばれる
  • なので bar.nameBar#name が呼ばれることを期待しているが実際には nil.name が呼ばれエラーになってしまう
  • これなんですが Ruby では変数が定義される構文があれば実行時にその処理が呼ばれなくても『変数が定義されている状態』になる
if false
  # ここは実行時に呼ばれない
  a = 42
end

# しかし、変数が定義されているように振る舞う
# 初期値は nil になっている
p a
# => nil
  • これにより提示されているコードでは bar = '' によって #bar メソッドが隠蔽され bar.name が意図する呼び出しにならない
  • Ruby になれていないと結構ぎょっとしまうねえ
GitHubで編集を提案

Discussion