Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
本当はこわい
エンコーディングの話
とみたまさひろ
東京Ruby会議10
2013-01-13
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
自己紹介
とみた まさひろ
http://tmtms.hatenablog.com
https://twitter.com/tmtms
好きなもの/環境
Ruby...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディング
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディングとは
文字符号化方式
文字をどのようなバイト列で表現するか
UTF-8 とか EUC-JP とか SHIFT_JIS と
かそーゆー奴
「char...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
同じバイト列でも別の文字
0xC2 0xA9 の2バイトは
UTF-8 では「©」1文字
EUC-JP では「息」1文字
SHIFT_JIS では「ツゥ」2文字
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
Ruby 1.8
"xC2xA9" という文字列は Ruby 的に
はただのバイト列
エンコーディング情報を持たない
"©"(UTF-8) として扱うか "息"(...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
Ruby 1.9
文字列のエンコーディングは文字列自身が
知っている
"©"(UTF-8) と "息"(EUC-JP) は同じバイ
ト列だけど異なる文字列
"あ"...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディング一覧(1.9.3)
Ruby 自身が持ってるので環境に依存しない
ASCII-8BIT Big5 Big5-HKSCS Big5-UAO CP50...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
うれしいこと
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
1.8ではバイト単位
"あいう".size #=> 9
"あいう".bytesize #=> 9
"あいう".chars{|c| ... }
#=> "xE3",...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
1.9では文字単位
"あいう".size #=> 3
"あいう".bytesize #=> 9
"あいう".chars{|c| ... }
#=> "あ", "い...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディング変換
# -*- coding: utf-8 -*-
s = "あいう"
#=> "xE3x81x82xE3x81x84xE3x81x86"
s....
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
IOで変換してくれる
File.open("cp932.txt", "r:CP932").read
#=> CP932 文字列
File.open("cp932....
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
うれしいことばかりじゃない
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
変換先にない文字
# -*- coding: utf-8 -*-
"あ♥".encode("CP932")
#=> Encoding::UndefinedConv...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
変換元にない文字
# -*- coding: utf-8 -*-
"あxFF".encode("CP932")
#=> Encoding::InvalidByte...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディングがあっても
変換できるとは限らない
# -*- coding: utf-8 -*-
"あいう".encode("UTF-7")
#=> Encod...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディングの不一致
utf8 = "あいう"
cp932 = "あ".encode("CP932")
utf8.start_with?(cp932)
#=>...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
文字列と正規表現の
エンコーディングの不一致
utf8 = "あいう"
re = /./s
utf8 =~ re
#=> Encoding::Compatibil...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディングが同じでも
不正な文字を含んでいる
utf8 = "あxFF"
utf8 =~ /./
#=> invalid byte sequence in ...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
IO
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
メソッドによって
エンコーディングが異なる
テキスト読み込み(エンコードあり)
IO#gets
IO#getc
IO#lines
IO#read 等
バイナリ読み...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
IO#read
IO#read(size) は ASCII-8BIT
IO#read() は外部エンコーディング依存
引数の有無によって結果のエンコーディ
ングが...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
外部エンコーディング
ファイル自身は自分の内容のエンコーデ
ィングを知らない
ファイルから読み込んだ文字列の Ruby
内でのエンコーディングは何らかの方法
で指...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
引数で指定
File.open(filename, "r:UTF-8")
File.read(filename, :encoding=>"UTF-8")
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
環境変数
引数で指定されてない場合は環境変数が参照
される
LC_ALL
LC_CTYPE
LANG
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
環境変数による違い
% cat utf-8.txt
あいうえお
% export LC_ALL=C
% ruby -e 'p File.read("utf-8.t...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
入力時にはエラーにならない
utf8 = File.read("utf8.txt", :encoding=>"UTF-8")
# 実は UTF-8 として不正な文...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
CGI
require "cgi"
cgi = CGI.new
不正な文字のパラメータを渡すとエラー
GET http://example.com/hoge.cg...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
Rails
不正な文字のパラメータを渡すとエラー
POST http://example.com/posts
post[title]=%FF
#=> Argume...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エラーになりすぎこわい!
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
対処
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
変換先にない文字を置換
"あ♥".encode("CP932")
#=> Encoding::UndefinedConversionError
"あ♥".enco...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
変換元にない文字を置換
"あxFF".encode("CP932")
#=> Encoding::InvalidByteSequenceError
"あxFF"....
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
置換文字の指定
"あ♥".encode("CP932", :undef=>:replace, :replace=>"〓")
#=> CP932 で "あ〓"
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
そもそも変換が必要になるような
ことをしないのが吉
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
UTF-8に統一すれば
たいていは問題ない
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
UTF-8に統一したつもりでも
他のエンコーディングが現れるこ
とも
File.open(filename, "r:UTF-8").read
#=> UTF-8 ...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
いちいち引数で指定する?
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
デフォルト値を指定する
プログラムで使用するファイルのエンコーディ
ングがすべて同一であれば
Encoding.default_external = "UTF-8...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
これで問題ない?
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
ASCII-8BIT
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
メソッドによっては ASCII-8BIT
f = File.open(filename, "r:UTF-8")
f.gets #=> UTF-8
f.read(1...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
ソケットは ASCII-8BIT
require 'socket'
Encoding.default_external = "UTF-8"
TCPSocket.n...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
気をつけるしかない
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
不正な文字
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
エンコーディングがUTF-8でも
データがUTF-8とは限らない
f = File.open("/dev/urandom", "r:UTF-8")
str = f...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
事前に判定
String#valid_encoding?
f = File.open("/dev/urandom", "r:UTF-8")
str = f.get...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
不正な文字を置換したい
簡単な方法はない
String#encode は変換元と変換先が同じ
場合は何もしない
# -*- coding: utf-8 -*-
"...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
Iconv ではできたけど…
require "iconv"
src = "あいxFFうえ"
dst = ""
iconv = Iconv.new("utf-8"...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
同じ文字群を持つ
別のエンコーディングを経由
"あxFF".
encode("UTF-16", :invalid=>:replace).
encode("UTF-...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
2.0.xだとできるようになる?
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
CGI や Rails
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
パラメータが不正な文字で
エラー
放置でいいんじゃない?
外部からの不正なデータは最前線でエラー
になってくれた方がありがたかったり
後の処理に渡されても扱いに困...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
CGIで頑張るなら
require 'cgi'
# 一旦 ASCII-8BIT で受けて
cgi = CGI.new :accept_charset=>"ASCI...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
Railsは...
よくわかりません (><)
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
おまけ
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
ASCII文字だけなら
異なるエンコーディングでも
エラーにならない
# -*- coding: utf-8 -*-
"あ" =~ /./s #=> Encodi...
本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6
まとめ
内部のエンコーディングは UTF-8 に統一
しよう
IO 読み込みで ASCII-8BIT になってるこ
とがある
外部からのデータは不正な文字が入って...
Upcoming SlideShare
Loading in …5
×

本当はこわいエンコーディングの話

Ruby Encoding

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

本当はこわいエンコーディングの話

  1. 1. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 本当はこわい エンコーディングの話 とみたまさひろ 東京Ruby会議10 2013-01-13
  2. 2. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 自己紹介 とみた まさひろ http://tmtms.hatenablog.com https://twitter.com/tmtms 好きなもの/環境 Ruby, Rabbit, MySQL, Emacs, Git, Ubuntu, ThinkPad 所属など 長野県北部在住 / 某社プログラマー / 日本 MySQLユーザ会 / 長野ソフトウェア技術者 グループ(NSEG)
  3. 3. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディング
  4. 4. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディングとは 文字符号化方式 文字をどのようなバイト列で表現するか UTF-8 とか EUC-JP とか SHIFT_JIS と かそーゆー奴 「charset」とか呼ばれたりする 「文字コード」とか呼ばれたりする
  5. 5. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 同じバイト列でも別の文字 0xC2 0xA9 の2バイトは UTF-8 では「©」1文字 EUC-JP では「息」1文字 SHIFT_JIS では「ツゥ」2文字
  6. 6. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 Ruby 1.8 "xC2xA9" という文字列は Ruby 的に はただのバイト列 エンコーディング情報を持たない "©"(UTF-8) として扱うか "息"(EUC-JP) として扱うかはプログラム次第 正規表現にはエンコーディングあり /〜/n /〜/s /〜/u /〜/e
  7. 7. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 Ruby 1.9 文字列のエンコーディングは文字列自身が 知っている "©"(UTF-8) と "息"(EUC-JP) は同じバイ ト列だけど異なる文字列 "あ"(UTF-8) と "あ"(EUC-JP) は同じ文 字を表してるけど等しくない 同じプログラム中で複数のエンコーディ ングの文字列を同時に扱える(珍しいかも) 正規表現にもエンコーディングあり
  8. 8. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディング一覧(1.9.3) Ruby 自身が持ってるので環境に依存しない ASCII-8BIT Big5 Big5-HKSCS Big5-UAO CP50220 CP50221 CP51932 CP850 CP852 CP855 CP949 CP950 CP951 EUC-JP EUC-KR EUC-TW Emacs-Mule GB12345 GB18030 GB1988 GB2312 GBK IBM437 IBM737 IBM775 IBM852 IBM855 IBM857 IBM860 IBM861 IBM862 IBM863 IBM864 IBM865 IBM866 IBM869 ISO-2022-JP ISO-2022-JP-2 ISO-2022-JP-KDDI ISO-8859-1 ISO-8859-10 ISO-8859-11 ISO-8859-13 ISO-8859-14 ISO-8859-15 ISO-8859-16 ISO-8859-2 ISO-8859-3 ISO-8859-4 ISO-8859-5 ISO-8859-6 ISO-8859-7 ISO-8859-8 ISO-8859-9 KOI8-R KOI8-U MacJapanese SJIS-DoCoMo SJIS-KDDI SJIS-SoftBank Shift_JIS TIS-620 US-ASCII UTF-16 UTF-16BE UTF-16LE UTF-32 UTF-32BE UTF-32LE UTF-7 UTF-8 UTF8-DoCoMo UTF8-KDDI UTF8-MAC UTF8-SoftBank Windows-1250 Windows-1251 Windows-1252 Windows-1253 Windows-1254 Windows-1255 Windows-1256 Windows-1257 Windows-1258 Windows-31J Windows-874 eucJP-ms macCentEuro macCroatian macCyrillic macGreek macIceland macRoman macRomania macThai macTurkish macUkraine stateless-ISO-2022-JP stateless-ISO-2022-JP-KDDI
  9. 9. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 うれしいこと
  10. 10. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 1.8ではバイト単位 "あいう".size #=> 9 "あいう".bytesize #=> 9 "あいう".chars{|c| ... } #=> "xE3","x81","x82", ... "あいう"[0] #=> 0xE3 "あいう".reverse #=> "x86x81xE3x84x81xE3x82x81xE3"
  11. 11. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 1.9では文字単位 "あいう".size #=> 3 "あいう".bytesize #=> 9 "あいう".chars{|c| ... } #=> "あ", "い", "う" "あいう"[0] #=> "あ" "あいう".reverse #=> "ういあ"
  12. 12. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディング変換 # -*- coding: utf-8 -*- s = "あいう" #=> "xE3x81x82xE3x81x84xE3x81x86" s.encoding #=> #<Encoding:UTF-8> s2 = s.encode("CP932") #=> "x82xA0x82xA2x82xA4" s2.encoding #=> #<Encoding:Windows-31J>
  13. 13. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 IOで変換してくれる File.open("cp932.txt", "r:CP932").read #=> CP932 文字列 File.open("cp932.txt", "r:CP932:UTF-8").read #=> UTF-8 文字列 File.open("cp932.txt").read #=> 環境依存
  14. 14. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 うれしいことばかりじゃない
  15. 15. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 変換先にない文字 # -*- coding: utf-8 -*- "あ♥".encode("CP932") #=> Encoding::UndefinedConversionError
  16. 16. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 変換元にない文字 # -*- coding: utf-8 -*- "あxFF".encode("CP932") #=> Encoding::InvalidByteSequenceError
  17. 17. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディングがあっても 変換できるとは限らない # -*- coding: utf-8 -*- "あいう".encode("UTF-7") #=> Encoding::ConverterNotFoundError
  18. 18. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディングの不一致 utf8 = "あいう" cp932 = "あ".encode("CP932") utf8.start_with?(cp932) #=> Encoding::CompatibilityError
  19. 19. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 文字列と正規表現の エンコーディングの不一致 utf8 = "あいう" re = /./s utf8 =~ re #=> Encoding::CompatibilityError
  20. 20. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディングが同じでも 不正な文字を含んでいる utf8 = "あxFF" utf8 =~ /./ #=> invalid byte sequence in UTF-8 # (ArgumentError)
  21. 21. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 IO
  22. 22. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 メソッドによって エンコーディングが異なる テキスト読み込み(エンコードあり) IO#gets IO#getc IO#lines IO#read 等 バイナリ読み込み(ASCII-8BIT固定) IO#read(n) IO#sysread 等
  23. 23. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 IO#read IO#read(size) は ASCII-8BIT IO#read() は外部エンコーディング依存 引数の有無によって結果のエンコーディ ングが異なる! なにそれこわい
  24. 24. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 外部エンコーディング ファイル自身は自分の内容のエンコーデ ィングを知らない ファイルから読み込んだ文字列の Ruby 内でのエンコーディングは何らかの方法 で指定する必要がある
  25. 25. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 引数で指定 File.open(filename, "r:UTF-8") File.read(filename, :encoding=>"UTF-8")
  26. 26. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 環境変数 引数で指定されてない場合は環境変数が参照 される LC_ALL LC_CTYPE LANG
  27. 27. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 環境変数による違い % cat utf-8.txt あいうえお % export LC_ALL=C % ruby -e 'p File.read("utf-8.txt").size' 16 % export LC_ALL=ja_JP.UTF-8 % ruby -e 'p File.read("utf-8.txt").size' 6 環境変数によって動きが変わっちゃう!こわい
  28. 28. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 入力時にはエラーにならない utf8 = File.read("utf8.txt", :encoding=>"UTF-8") # 実は UTF-8 として不正な文字が含まれていて 〜〜〜〜〜〜 # ずっと後で別のメソッドでエラーになったり utf8 =~ /./ #=> invalid byte sequence in UTF-8 (ArgumentError)
  29. 29. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 CGI require "cgi" cgi = CGI.new 不正な文字のパラメータを渡すとエラー GET http://example.com/hoge.cgi?fuga=%FF #=> Accept-Charset encoding error (CGI::InvalidEncoding)
  30. 30. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 Rails 不正な文字のパラメータを渡すとエラー POST http://example.com/posts post[title]=%FF #=> ArgumentError (invalid byte sequence in UTF-8)
  31. 31. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エラーになりすぎこわい!
  32. 32. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 対処
  33. 33. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 変換先にない文字を置換 "あ♥".encode("CP932") #=> Encoding::UndefinedConversionError "あ♥".encode("CP932", :undef=>:replace) #=> "あ?"
  34. 34. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 変換元にない文字を置換 "あxFF".encode("CP932") #=> Encoding::InvalidByteSequenceError "あxFF".encode("CP932", :invalid=>:replace) #=> "あ?"
  35. 35. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 置換文字の指定 "あ♥".encode("CP932", :undef=>:replace, :replace=>"〓") #=> CP932 で "あ〓"
  36. 36. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 そもそも変換が必要になるような ことをしないのが吉
  37. 37. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 UTF-8に統一すれば たいていは問題ない
  38. 38. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 UTF-8に統一したつもりでも 他のエンコーディングが現れるこ とも File.open(filename, "r:UTF-8").read #=> UTF-8 文字列 File.open(filename).read #=> 環境依存
  39. 39. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 いちいち引数で指定する?
  40. 40. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 デフォルト値を指定する プログラムで使用するファイルのエンコーディ ングがすべて同一であれば Encoding.default_external = "UTF-8" File.read(filename) #=> UTF-8文字列
  41. 41. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 これで問題ない?
  42. 42. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 ASCII-8BIT
  43. 43. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 メソッドによっては ASCII-8BIT f = File.open(filename, "r:UTF-8") f.gets #=> UTF-8 f.read(10) #=> ASCII-8BIT
  44. 44. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 ソケットは ASCII-8BIT require 'socket' Encoding.default_external = "UTF-8" TCPSocket.new('127.0.0.1', 25).gets #=> ASCII-8BIT
  45. 45. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 気をつけるしかない
  46. 46. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 不正な文字
  47. 47. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 エンコーディングがUTF-8でも データがUTF-8とは限らない f = File.open("/dev/urandom", "r:UTF-8") str = f.gets str.encoding #=> #<Encoding:UTF-8> str =~ /./ #=> invalid byte sequence in UTF-8 (ArgumentError)
  48. 48. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 事前に判定 String#valid_encoding? f = File.open("/dev/urandom", "r:UTF-8") str = f.gets str.valid_encoding? #=> false
  49. 49. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 不正な文字を置換したい 簡単な方法はない String#encode は変換元と変換先が同じ 場合は何もしない # -*- coding: utf-8 -*- "あxFF".encode("CP932", :invalid=>:replace) #=> "あ?" "あxFF".encode("UTF-8", :invalid=>:replace) #=> "あxFF"
  50. 50. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 Iconv ではできたけど… require "iconv" src = "あいxFFうえ" dst = "" iconv = Iconv.new("utf-8", "utf-8") begin dst.concat iconv.iconv(src) rescue Iconv::IllegalSequence => e dst.concat e.success dst.concat "〓" src = e.failed[1..-1] retry end dst #=> "あい〓うえ" Iconv は 2.0 で廃止
  51. 51. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 同じ文字群を持つ 別のエンコーディングを経由 "あxFF". encode("UTF-16", :invalid=>:replace). encode("UTF-8") #=> "あ�"
  52. 52. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 2.0.xだとできるようになる?
  53. 53. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 CGI や Rails
  54. 54. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 パラメータが不正な文字で エラー 放置でいいんじゃない? 外部からの不正なデータは最前線でエラー になってくれた方がありがたかったり 後の処理に渡されても扱いに困るだけ 実害はログが鬱陶しいくらい?
  55. 55. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 CGIで頑張るなら require 'cgi' # 一旦 ASCII-8BIT で受けて cgi = CGI.new :accept_charset=>"ASCII-8BIT" # パラメータ毎にどうにかする hoge = cgi['hoge'].encode("UTF-8", "UTF-8") unless hoge.valid_encoding? ...
  56. 56. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 Railsは... よくわかりません (><)
  57. 57. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 おまけ
  58. 58. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 ASCII文字だけなら 異なるエンコーディングでも エラーにならない # -*- coding: utf-8 -*- "あ" =~ /./s #=> Encoding::CompatibilityError "ABC" =~ /./s #=> エラーにならない ASCII文字だけでテストしてると本番でエラー になったりこわい
  59. 59. 本当はこわいエンコーディングの話 Powered by Rabbit 2.0.6 まとめ 内部のエンコーディングは UTF-8 に統一 しよう IO 読み込みで ASCII-8BIT になってるこ とがある 外部からのデータは不正な文字が入ってる ことがある ちゃんと気をつければそんなにこわくない

    Be the first to comment

    Login to see the comments

  • KatokichiSoft

    Jan. 5, 2015
  • konishika

    Jan. 6, 2015
  • matchy

    Jan. 10, 2015
  • nakazawayuichi

    Apr. 22, 2015
  • ryudoawaru

    Apr. 23, 2015

Ruby Encoding

Views

Total views

4,001

On Slideshare

0

From embeds

0

Number of embeds

56

Actions

Downloads

8

Shares

0

Comments

0

Likes

5

×