From: Yusuke ENDOH Date: 2005-09-28T01:47:27+09:00 Subject: [ruby-dev:27334] File#read にゴミがつく はじめまして、遠藤侑介と申します。 ruby 1.8.3 にバグらしきものを見つけたので報告致します。 (もし既知でしたらすみません) IO#read が EOF の後に勝手に 0xFF を追加してしまいます。 $ od -c foo 0000000 f o o \n 0000004 $ ./miniruby -e 'File.open("foo") { |r| p r.read }' "foo\n\377" # このため make install すると # 全てのファイルの末尾に 0xFF が追加されてしまい ruby が実行できません。 原因を探ってみたところ、 関数 read_buffered_data 内で以下のようなコードがあり、 1023 for (n = 0; n < len && READ_DATA_PENDING(f); ++n) { 1024 *ptr++ = getc(f); 1025 } 1026 return n; さらに私がコンパイルした環境 (SPARCv9, gcc 3.3.2) では マクロ READ_DATA_PENDING(fp) が (!feof(fp)) に展開されていました。 (環境: sparc-solaris2.9, gcc 3.3.2) feof は getc などで EOF に達した後でないと non-zero を返さないので、 ループが一回多く回ってしまい、今回の現象が発生するのだと思います (多分) 。 以下のように修正すると正常に動作する事を確認しました。 --- ruby-1.8.3.old/io.c Tue Sep 27 23:09:50 2005 +++ ruby-1.8.3.new/io.c Tue Sep 27 23:21:54 2005 @@ -153,8 +153,20 @@ #else /* requires systems own version of the ReadDataPending() */ extern int ReadDataPending(); -# define READ_DATA_PENDING(fp) (!feof(fp)) +# define READ_DATA_PENDING(fp) (!pending_p(fp)) # define READ_DATA_BUFFERED(fp) 0 +int pending_p(fp) + FILE *fp; +{ + char c; + + c = getc(fp); + if (c == EOF) { + return 1; + } + ungetc(c, fp); + return 0; +} #endif #ifndef READ_DATA_BUFFERED # define READ_DATA_BUFFERED(fp) READ_DATA_PENDING(fp) -- Yusuke ENDOH