LoginSignup
3
1

More than 5 years have passed since last update.

Ruby 2.4.0 の CSV の field_size_limit: オプションの挙動が変わった?

Last updated at Posted at 2017-01-23

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

修正されました。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1