From: Masahiro Tomita Date: 2011-11-15T15:51:36+09:00 Subject: [ruby-dev:44875] [ruby-trunk - Bug #5635][Open] String#unpack("M") の不正データ時の振る舞い Issue #5635 has been reported by Masahiro Tomita. ---------------------------------------- Bug #5635: String#unpack("M") の不正データ時の振る舞い http://redmine.ruby-lang.org/issues/5635 Author: Masahiro Tomita Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.3p0 (2011-11-08 revision 33661) [i686-linux] String#unpack("M") で "=hoge" みたいな不正なデータがあった場合、現在は そこで処理を中断してしまっていますが、それ以降のデータをすべて捨ててし まうのはかわいそうなので、ポインタを一つ進めて処理を継続した方がいいん じゃないかと思うのですがどうでしょうか。 RFC2045 には次のような記述があります。 (2) An "=" followed by a character that is neither a hexadecimal digit (including "abcdef") nor the CR character of a CRLF pair is illegal. This case can be the result of US-ASCII text having been included in a quoted-printable part of a message without itself having been subjected to quoted-printable encoding. A reasonable approach by a robust implementation might be to include the "=" character and the following character in the decoded data without any transformation and, if possible, indicate to the user that proper decoding was not possible at this point in the data. Index: pack.c =================================================================== --- pack.c (リビジョン 33758) +++ pack.c (作業コピー) @@ -2008,20 +2008,23 @@ while (s < send) { if (*s == '=') { - if (++s == send) break; - if (s+1 < send && *s == '\r' && *(s+1) == '\n') - s++; - if (*s != '\n') { - if ((c1 = hex2num(*s)) == -1) break; - if (++s == send) break; - if ((c2 = hex2num(*s)) == -1) break; - *ptr++ = c1 << 4 | c2; + if (s+1 < send && *(s+1) == '\n') { + s += 2; + continue; + } + if (s+2 < send) { + if (*(s+1) == '\r' && *(s+2) == '\n') { + s += 3; + continue; + } + if ((c1 = hex2num(*(s+1))) > -1 && (c2 = hex2num(*(s+2))) > -1) { + *ptr++ = c1 << 4 | c2; + s += 3; + continue; + } } } - else { - *ptr++ = *s; - } - s++; + *ptr++ = *s++; } rb_str_set_len(buf, ptr - RSTRING_PTR(buf)); ENCODING_CODERANGE_SET(buf, rb_ascii8bit_encindex(), ENC_CODERANGE_VALID); Index: test/ruby/test_pack.rb =================================================================== --- test/ruby/test_pack.rb (リビジョン 33758) +++ test/ruby/test_pack.rb (作業コピー) @@ -612,6 +612,17 @@ assert_equal([0x100000000], "\220\200\200\200\000".unpack("w"), [0x100000000]) end + def test_pack_unpack_M + assert_equal(["pre123after"], "pre=31=32=33after".unpack("M")) + assert_equal(["preafter"], "pre=\nafter".unpack("M")) + assert_equal(["preafter"], "pre=\r\nafter".unpack("M")) + assert_equal(["pre="], "pre=".unpack("M")) + assert_equal(["pre=\r"], "pre=\r".unpack("M")) + assert_equal(["pre=hoge"], "pre=hoge".unpack("M")) + assert_equal(["pre=1after"], "pre==31after".unpack("M")) + assert_equal(["pre==1after"], "pre===31after".unpack("M")) + end + def test_modify_under_safe4 s = "foo" assert_raise(SecurityError) do -- http://redmine.ruby-lang.org