質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

1084閲覧

変数に代入したものをプログラムとして実行させたい

tampopoo2

総合スコア6

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2020/10/08 01:47

前提・実現したいこと

変数に代入したものをプログラムとして実行させて標準出力をし、aという出力結果を表示したいです。
@test1ではProcに直接内容を書き込むことで、aを出力することができました。
testの内容はテーブルから抽出する予定なので1度変数を挟む必要があると思い、
@test2_preで内容を代入し、その後@test2でProcに変数を渡して実行しました。
しかし、実行結果はprint 'a'となりました。
変数を挟む@test2の場合にaと出力させるにはどのようにすれば良いでしょうか。

該当のソースコード

Ruby

1t1_filename = './test1.txt' # 実行結果ファイル名 2t2_filename = './test2.txt' # 実行結果ファイル名 3 4#実行させたい内容 5@test1 = Proc.new{print 'a'} 6 7@test2_pre = "print 'a'" 8@test2 = Proc.new {@test2_pre} 9 10# 実行結果を test1.txt に出力 11 $stdout = File.open(t1_filename, 'w') 12 puts @test1.call 13 $stdout.close 14 $stdout = STDOUT 15 16# 実行結果を test2.txt に出力 17 $stdout = File.open(t2_filename, 'w') 18 puts @test2.call 19 $stdout.close 20 $stdout = STDOUT 21 22# ファイルの読み込み 23@test1_post = File.read(t1_filename) 24@test2_post = File.read(t2_filename) 25 26#結果の出力 27print "test1の結果:#{@test1_post}" 28print "test2の結果:#{@test2_post}"

実行結果

test1の結果:a
test2の結果:print 'a'

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/10/08 01:54

Railsはどれくらい関係するのでしょうか? (Railsのような、インターネットに向けて公開するもので「ユーザー入力を実行する」ようなことをやろうとすれば、考えることは一気に増えます)
tampopoo2

2020/10/08 22:13

maisumakunさんのおっしゃる通りで、使用対象は特定のユーザーのみではありますが、インターネットで公開し、ユーザーが入力したものを実行する予定です。考えることは一気に増えるということは悪意のあるユーザーからの攻撃を受けるということでしょうか。
guest

回答2

0

ベストアンサー

変数を挟むことは本質でなくて、@test2 = Proc.new {"print 'a'"}と書いても同じです。

それは、「print 123と書くと123と出力されるが、123だけ書いても何も起こったように見えない」というのと同じです。"print 'a'"は単なる文字列なので。

文字列を実行するにはevalを使います。
DBから取り出した文字列をevalするというのはそこだけ見れば問題ないです(※)が、そのDBに格納するデータがユーザー入力由来の物であれば、悪意を持ったユーザーが、重要データを流出・改ざん・削除するようなRubyプログラムに相当する文字列を入力すると困った事態になりますので、要注意です。
一般的には、処理の種類だけDBに格納しておいて、そのデータを(直接実行するのでなく)見て処理を変えるのが良いです。

※:そこのテーブルデータ書き換えが、プログラム自体の修正と同じレベルで管理されいる場合。

投稿2020/10/08 02:38

otn

総合スコア85962

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tampopoo2

2020/10/08 22:20

回答ありがとうございます。 課題点がずれていて、理解ができていなかったですね。恥ずかしい。 evalはすごく便利なものとして受け取っていましたが、使用するユーザーによっては恐ろしいものとなるのですね。 直接実行させようとしていました、危険でしたね。ありがとうございます!
guest

0

次のコードを研究してみてください、

ruby

1require 'stringio' 2 3# 実行させたい内容 4tests = [ 5 proc { print 'a' }, 6 proc { "print 'a'" }, 7 'print "a"', 8 'system "date"'.taint # 危険な文 9 # ")" # 不正な文 10] 11 12$SAFE = 1 13tests.map.with_index do |statement, idx| 14 # 実行結果を capture 15 $stdout = StringIO.new 16 17 begin 18 if statement.is_a? String 19 eval(statement) 20 else 21 puts statement.call 22 end 23 rescue StandardError => e 24 print e 25 end 26 27 # capture 結果を出力 28 STDOUT.puts "#{idx + 1} の結果:#{$stdout.string}" 29end

eval、$SAFE の挙動は ruby verisn で異なります。注意が必要です。

実行例
イメージ説明

参考情報

  • ルービー3分クッキング「今日はオブジェクトを汚染していきます」

https://qiita.com/namitop/items/1932a7610ca1f819588c

投稿2020/10/08 21:45

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tampopoo2

2020/10/08 22:53

非常に参考になる内容で、ありがたいです。 セキュリティ面に関して手をつけていなかったので大変助かりました。 まだまだ理解できていない部分多いので、 勉強しながら研究していこうと思います。 コードまで丁寧に教えてくださり、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問