3

私は宿題をし、このトピックに関する他の回答を研究しましたが、私の特定の問題に対処するものはありません。

ioライブラリを完全に削除し、osを部分的にのみ削除したい(os.clock()などを保持したい場合)

CAPIからのみこれを実現するにはどうすればよいですか。

プロジェクトの性質上、Luaヘッダーと送信されるスクリプトを変更することは許可されていません。これらは私の管理下にはありません。私が変更できるのはインタプリタだけです。

このようなことをする:

lua_pushnil(state_pointer);
lua_setglobal(state_pointer, "os.execute");

スクリプトでは、ユーザーがos = require('os')を呼び出して、すべての関数を取り戻すことができるため、あまり役に立ちません。

require関数を無効にすることは許可されていないので、これは物事を難しくします。

何か案は?

PS:もっと好奇心があります:私が次のようなことをした場合

luaopen_base(L);
luaopen_table(L);
luaopen_string(L);
luaopen_math(L);
luaopen_loadlib(L); (basically i'm loading every library by hand except os and io)

それ以外の

luaL_openlibs(L); (this loads all the libraries)

os = require('os')またはio = require('io')は引き続き機能しますか?


@Nicol Bolasは、私が何か間違ったことをしているのかどうかわかりませんが、os = require('os')&require('io')はすべてを元に戻します。

私のコード:

luaL_openlibs(LuaInstance);     /* load the libs        */ 
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "io");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.execute");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.rename");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.remove");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.exit");

私のスクリプトでは、

os = require('os')
io = require('io')

この後、os関数とio関数はすべて機能します。os.exitは引き続きアプリを閉じ、io.writeは通常どおり機能します

4

2 に答える 2

7

スクリプトでは、ユーザーがos = require('os')を呼び出して、すべての関数を取り戻すことができるため、あまり役に立ちません。

いいえ、ありません。呼び出すrequire(os)と、テーブルが返されosます。変更したのと同じテーブル。ですから問題ありません。

したがって、登録後にテーブルを変更するだけです。それは機能します、そしてそれが機能することをテストすることは本当に簡単です。

luaopen_base(L);

注意:luaopen_*通常のC関数ではありません。それらはLuaC関数です。これらは、標準のLuaメカニズムを介して呼び出されることを期待する関数です。Cから直接呼び出すことはできません。

lua_pcallLua 5.1では、それらをスタックにプッシュし、または同様の呼び出し関数を使用してそれらを呼び出す必要があります。Lua 5.2では、を使用する必要があります。luaL_requirefこれにより、テーブルがLuarequireレジストリに配置されます。


コードには2つの問題があります。初め:

lua_setglobal(LuaInstance, "io");
lua_pushnil(LuaInstance);

これは実際にはテーブルを変更しません。テーブルへの参照を削除するだけです。テーブル自体を変更する場合は、テーブルを変更する必要があります。ioテーブルを取得して変更する必要があります。テーブルを歩き、テーブル内の各値をに設定しますnil。呼び出されたグローバル変数の内容を置き換えるだけでioは何も起こりません。

ただし、io完全に使用されないようにする場合は、最初から登録しないでください。

2番目の問題はこれです:

lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.execute");

これにより、キーがであるグローバルテーブルの値が変更されます["os.execute"]。これは、このLuaコードと同等です。

_G["os.execute"] = nil

これは次のものと同じではありません。

os.execute = nil;

os.executeLuaで使用する場合、それはグローバルテーブル( _G)を取得し、名前が付けられたキーを持つ値を見つけ、からフェッチされたテーブル内のキー"os"を見つけることを意味します。"execute""os"

あなたがそうするとき_G["os.execute"]、あなたが言っていることは、グローバルテーブルを取り、という名前のキーで値を見つけることです"os.execute"

違いを見ます?

あなたがしたいのは、グローバル変数に格納されているテーブルを取得し、そのosテーブルを変更することです。テーブルのメンバーはグローバルではないため、を使用することはできません。彼らはテーブルのメンバーです。はい、それらが格納されているテーブルはたまたまグローバルです。ただし、グローバルに格納されているテーブルのメンバーを。で変更することはできません。lua_setglobaloslua_setglobal

あなたはこれをしなければなりません:

lua_getglobal(L, "os");
lua_pushnil(L);
lua_setfield(L, -2, "execute");
lua_pushnil(L);
lua_setfield(L, -2, "rename");
lua_pushnil(L);
lua_setfield(L, -2, "remove");
lua_pushnil(L);
lua_setfield(L, -2, "exit");
lua_pop(L, 1);
于 2012-04-11T15:50:24.167 に答える
3

サンドボックスの使用をお勧めします。「安全なLuaサンドボックスを作成する方法」を参照してください。

の場合require、実際のバージョンを呼び出す前にパラメーターを検証する独自のラッパーを作成し、サンドボックスにラッパーのみを含めます。

于 2012-04-11T17:37:01.430 に答える