From: Satoshi Nakagawa Date: 2007-12-10T19:27:17+09:00 Subject: [ruby-dev:32518] bug in Array#slice! 中川といいます。 [ruby-dev:31761] で一度レポートしたのですが、Array の基 本的なところのバグで重要だと思われるので、もう一度詳しくレ ポートします。 Array#slice! で、負の範囲外の index を指定した場合、例 外にならないことがあります。 trunk と 1.8 で再現します。 具体的には、 $ ./ruby -e 'a = %w|a b c d e|; a.slice!(-3,2); p a' ["a", "b", "e"] $ ./ruby -e 'a = %w|a b c d e|; a.slice!(-8,2); p a' ["a", "b", "e"] のような場合です。 この場合、-3 と -8 が同一視されてしまっています。 $ ./ruby -e 'a = %w|a b c d e|; a.slice!(-13,2); p a' -e:1:in `slice!': index -8 out of array (IndexError) from -e:1:in `
' ためしに -13 を指定すると、index -8 は範囲外だと いうエラーになるので、どこかで Array#size を誤って足し てしまっていることがわかります。 ソースを見ると、rb_ary_slice_bang 自体と、そこから呼んでい る rb_ary_splice で2度足し込んでしまっているようです。 以下のパッチで、 $ ./ruby -e 'a = %w|a b c d e|; a.slice!(-3,2); p a' ["a", "b", "e"] $ ./ruby -e 'a = %w|a b c d e|; a.slice!(-8,2); p a' -e:1:in `slice!': index -8 out of array (IndexError) from -e:1:in `
' と正しく動作することを確認しました。 Index: array.c =================================================================== --- array.c (revision 14178) +++ array.c (working copy) @@ -1886,9 +1886,6 @@ pos = NUM2LONG(arg1); len = NUM2LONG(arg2); delete_pos_len: - if (pos < 0) { - pos = RARRAY_LEN(ary) + pos; - } arg2 = rb_ary_subseq(ary, pos, len); rb_ary_splice(ary, pos, len, Qundef); /* Qnil/rb_ary_new2(0) */ return arg2; -- Satoshi Nakagawa