field_size_limit:
オプションを使っているコードを Ruby 2.4.0 で動かしたところ、エラーを期待したテストケースがエラーにならなくなりました。
This is a maximum size CSV will read ahead looking for the closing quote for a field. (In truth, it reads to the first line ending beyond this size.) If a quote cannot be found within the limit CSV will raise a MalformedCSVError, assuming the data is faulty. You can use this limit to prevent what are effectively DoS attacks on the parser. However, this limit can cause a legitimate parse to fail and thus is set to +nil+, or off, by default.
https://docs.ruby-lang.org/ja/latest/class/CSV.html
自分の理解としては、閉じクォートを探すための先読みを何文字まで許すか指定するためのオプションというもの。以下のサンプルコードの場合、2行目の一列目の引用符内が \n2\n
で 4 文字未満を満たしているのでエラーにはならないはず。
require 'csv'
CSV.new(DATA, field_size_limit: 4).each { |x| p x }
__END__
"a","b"
"
2
",""
実際、Ruby 2.3.3 で実行すると正常終了する。
$ ruby test.rb
["a", "b"]
["\n2\n", ""]
一方、Ruby 2.4.0 で実行すると例外終了してしまう。
$ ruby test.rb
["a", "b"]
~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1931:in `block in shift': Field size exceeded on line 2. (CSV::MalformedCSVError)
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `loop'
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `shift'
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1770:in `each'
from test.rb:3:in `<main>'
よく分からないので field_size_limit:
オプションで指定した上限値との比較をしている近辺でどんなデータを保持しているのか、以下のプリントデバッグで見てみた。
--- ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb.orig 2017-01-23 11:55:00.000000000 +0900
+++ ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb 2017-01-23 11:55:05.000000000 +0900
@@ -1923,6 +1923,7 @@
csv[-1][-1] = @row_sep if in_extended_col
if in_extended_col
+ p csv.last, csv.last.size
# if we're at eof?(), a quoted field wasn't closed...
if @io.eof?
raise MalformedCSVError,
文字列ではなく配列で保持する様になり、その要素数で比較しているという事だろうか。
$ ruby test.rb
["a", "b"]
["", "\n"]
2
["", "\n", "1", "\n"]
4
~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1932:in `block in shift': Field size exceeded on line 2. (CSV::MalformedCSVError)
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `loop'
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1828:in `shift'
from ~/.rbenv/versions/2.4.0/lib/ruby/2.4.0/csv.rb:1770:in `each'
from test.rb:3:in `<main>'
取り急ぎ、メモ。
追記
(日本語ながら)ひとまず報告をしてみた。
追記2
修正されました。