1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【初心者向け】Ruby のまずいコード 25 本Advent Calendar 2021

Day 12

【Ruby のまずいコード】ファイル書き出し

Last updated at Posted at 2021-12-11

お題

Math::PI の値をファイル pi.txt に書き出してください。

コード

File.open("pi.txt", "w") do |f|
  f.print Math::PI
end

改善

ファイルに書き出す専用のメソッド IO.write があります。
これを用いると

IO.write("pi.txt", Math::PI)

と簡素化できます。
IO.writeFile.write とも書けます。これについては次節で述べます。

ファイル読み込みのほうも同様で,

text = nil
File.open("text.txt") do |f|
  text = f.read
end

とか1

text = File.open("text.txt"){ |f| f.read }

などとしなくても,IO.read を使って

text = IO.read("text.txt")

と書けます。
IO.readFile.read とも書けます(次節参照)。

IO.write/IO.read か File.write/File.read か

IO.readIO.write を使ったコードを RuboCop で検査すると,セキュリティーの観点から「IO.write でなく File.write を使う」ように言われます2

というのは,File.readFile.write はファイルの読み書きしかできませんが,IO.readIO.write はファイル以外のさまざまなものに対しても読み書きでき,第一引数に与えるものによってはコマンドの実行すらできてしまうからです。
例えば,

IO.read("| mkdir hoge")

とやると,ディレクトリーが作れてしまいます!3
よって,たとえばウェブアプリでユーザー入力に基づく値を第一引数に与えることはコマンドインジェクション攻撃に繋がり得ます。

そういう観点からすると,この記事の対象読者(初心者を想定)に IO.writeIO.read を勧めるのは良くない気もしますね。
File.writeFile.read を使う,と覚えておいたほうがよいかもしれません。

  1. このコードでわざわざ text = nil としているのは,ブロック外でローカル変数を定義しないとこのあとで text が使えないから。代入される nil に意味はありません。原理的には何でも OK ですが,nil 以外だと何か意味のある値なのかと誤解される恐れがあります。

  2. 検出されるかどうかは RuboCop の設定によります。

  3. もちろんもっと怖いこともできます。ここでは,macOS,Linux,Windows で共通に使えるコマンドを例に取りました。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?