2012-07-01 15 views
5

私はRoberto Ierusalimschyの "Programing in Lua"から学んでいますが、本書ではSandboxingの例では、関数setfenv()を使用して特定の関数の環境を変更していますが、機能はもはや利用できません。Luaのサンドボックス化5.2

ファイル(構成ファイル)からテーブルのフィールドに値をロードしようとしましたが、ルア5.2ではsetfenvを使用できません(指定された環境で値をロードできます)。 「サンドボックス」で

function sandbox(sb_func, sb_env) 
    if not sb_func then return nil, "sandbox function not valid" end 
    sb_orig_env = _ENV 
    _ENV = sb_env -- yes, replaces the global _ENV 
    pcall_res, message = pcall(sb_func) 
    local modified_env = _ENV -- gets the environment that was used in the pcall(sb_func) 
    _ENV = sb_orig_env 
    return true, modified_env 
end 

function readFile(filename) 
    code = loadfile(filename) 
    res, table = sandbox(code, {}) 
    if res then 
     --[[ Use table (modified_env) ]]-- 
    else 
     print("Code not valid") 
end 

_ENVを交換:LUA 5.2についてのいくつかの記事を読んだ後、私は、次のコードを試み、各関数は環境として機能_ENVと呼ばれる上位値を有する(またはしない)ことが見出され、これ(通常のフィールドにはアクセスできませんが) 'code'が実行されると、_ENVを置き換えても無視されるようですが、通常のフィールド(print、loadfile、dofileなど)にはまだアクセスできます。

もう少し読んで、私はこの目的のための関数を提供することを発見しました。この関数はloadin(env, chunk)です。与えられた環境で与えられたチャンクを実行しますが、この関数を自分のコードに追加しようとすると、関数が存在しません(グローバル_Gフィールドには存在しません)。

何か助けていただければ幸いです。現在実行中のコードの_ENV上位値を置き換えるyou're - あなたは​​内から_ENVに割り当てるとき

答えて

7

、あなたは地球環境を上書きしじゃありません。 print(_ENV)への通話を追加すると、関連するテーブルのIDをよりよく理解するのに役立ちます。例えば

function print_env() 
    print(_ENV) 
end 

function sandbox() 
    print(_ENV) -- prints: "table: 0x100100610" 
    -- need to keep access to a few globals: 
    _ENV = { print = print, print_env = print_env, debug = debug, load = load } 
    print(_ENV) -- prints: "table: 0x100105140" 
    print_env() -- prints: "table: 0x100105140" 
    local code1 = load('print(_ENV)') 
    code1()  -- prints: "table: 0x100100610" 
    debug.setupvalue(code1, 1, _ENV) -- set our modified env 
    code1()  -- prints: "table: 0x100105140" 
    local code2 = load('print(_ENV)', nil, nil, _ENV) -- pass 'env' arg 
    code2()  -- prints: "table: 0x100105140" 
end 

loadin関数はLuaの5.2のいくつかのプレリリースバージョンに存在したが、最終的なリリースの前に除去しました。代わりに、Lua 5.2 load and loadfile functionsenv引数をとります。 debug.setupvalueを使用して別の機能の_ENVを変更することもできます。

+1

ありがとうございます!解決は簡単でした。 'setfenv'がロードされたコードで使われていたので、' load'と 'loadfile'で環境を変更するこのアプローチがより良いと思います...ありがとう!私は期待どおりにサンドボックス化しました。 –

+0

@Miles print_env()が定義されているときに、グローバル_ENVを上位値として受け取っていませんか? print_env()がsandbox()の内側で呼び出されたとき、どのように変更されましたか? –

+1

@TiagoCosta upvaluesは外部ローカル変数です。この場合の '_ENV'はチャンクに対してローカルです。 '_ENV'への代入はチャンクローカル変数に影響します。これは両方のクロージャの共有されたupvalueです。 – Miles

関連する問題