💡

[Bug #20701] 特定の条件で ** で渡した Hash オブジェクトの値が変わってしまうバグ報告

2024/08/27に公開

[Bug #20701] Hash argument passed as keyword splat can be mutated inside method

  • 通常 ** で Hash オブジェクトの値は書き換わらないようになっています
def foo(a, h)
  # ここで h の値を書き変える
  h[:splat_modified] = true
end

b = { splat_modified: false }
# ** で渡した場合は b の値は変わらない
foo(1, **b)
pp b
# => {:splat_modified=>false}
  • しかし、次のように特定のケースでメソッドに渡した場合に Hash オブジェクトの値が意図せず書き換わってしまうというバグ報告
def foo(a, h)
  h[:splat_modified] = true
end

b = { splat_modified: false }
# * と位置引数と ** で引数を渡す
# a = 2
# h = b
# となる
foo(*[], 2, **b)

# b の値が書き換わってしまう
pp b
# => {:splat_modified=>true}
# ** で受け取る場合も同様の挙動になる
def foo(a, **h)
  h[:splat_modified] = true
end

b = { splat_modified: false }
foo(*[], 2, **b)

pp b
# => {:splat_modified=>true}
  • この不具合は開発版の Ruby 3.4 ですでに修正済み
GitHubで編集を提案

Discussion