Upvalues: replace upvalue only if it's equal to _G (#110)
This commit is contained in:
parent
c5d94ec465
commit
2e4e219b85
@ -2,28 +2,6 @@
|
|||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool allowTableUpvalues(const sol::optional<bool>& newValue = sol::nullopt) {
|
|
||||||
static std::atomic_bool value(true);
|
|
||||||
|
|
||||||
if (newValue)
|
|
||||||
return value.exchange(newValue.value());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous
|
|
||||||
|
|
||||||
sol::object luaAllowTableUpvalues(sol::this_state state, const sol::stack_object& value) {
|
|
||||||
if (value.valid()) {
|
|
||||||
REQUIRE(value.get_type() == sol::type::boolean) << "bad argument #1 to 'effil.allow_table_upvalues' (boolean expected, got " << luaTypename(value) << ")";
|
|
||||||
return sol::make_object(state, allowTableUpvalues(value.template as<bool>()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return sol::make_object(state, allowTableUpvalues());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Function::Function(const sol::function& luaObject) {
|
Function::Function(const sol::function& luaObject) {
|
||||||
assert(luaObject.valid());
|
assert(luaObject.valid());
|
||||||
assert(luaObject.get_type() == sol::type::function);
|
assert(luaObject.get_type() == sol::type::function);
|
||||||
@ -38,30 +16,29 @@ Function::Function(const sol::function& luaObject) {
|
|||||||
ctx_->function = dumpFunction(luaObject);
|
ctx_->function = dumpFunction(luaObject);
|
||||||
ctx_->upvalues.resize(dbgInfo.nups);
|
ctx_->upvalues.resize(dbgInfo.nups);
|
||||||
#if LUA_VERSION_NUM > 501
|
#if LUA_VERSION_NUM > 501
|
||||||
ctx_->envUpvaluePos = 0; // means no _ENV upvalue
|
ctx_->envUpvaluePos = 0; // means no _G upvalue
|
||||||
|
|
||||||
|
lua_pushglobaltable(state);
|
||||||
|
const auto gTable = sol::stack::pop<sol::table>(state);
|
||||||
#endif // LUA_VERSION_NUM > 501
|
#endif // LUA_VERSION_NUM > 501
|
||||||
|
|
||||||
|
|
||||||
for (unsigned char i = 1; i <= dbgInfo.nups; ++i) {
|
for (unsigned char i = 1; i <= dbgInfo.nups; ++i) {
|
||||||
const char* valueName = lua_getupvalue(state, -1, i); // push value on stack
|
const char* valueName = lua_getupvalue(state, -1, i); // push value on stack
|
||||||
(void)valueName; // get rid of 'unused' warning for Lua5.1
|
(void)valueName; // get rid of 'unused' warning for Lua5.1
|
||||||
assert(valueName != nullptr);
|
assert(valueName != nullptr);
|
||||||
|
|
||||||
#if LUA_VERSION_NUM > 501
|
#if LUA_VERSION_NUM > 501
|
||||||
if (strcmp(valueName, "_ENV") == 0) { // do not serialize _ENV
|
if (gTable == sol::stack::get<sol::table>(state)) { // do not serialize _G
|
||||||
sol::stack::pop<sol::object>(state);
|
sol::stack::pop<sol::object>(state);
|
||||||
ctx_->envUpvaluePos = i;
|
ctx_->envUpvaluePos = i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif // LUA_VERSION_NUM > 501
|
#endif // LUA_VERSION_NUM > 501
|
||||||
|
|
||||||
const auto& upvalue = sol::stack::pop<sol::object>(state); // pop from stack
|
|
||||||
if (!allowTableUpvalues() && upvalue.get_type() == sol::type::table) {
|
|
||||||
sol::stack::pop<sol::object>(state);
|
|
||||||
throw effil::Exception() << "bad function upvalue #" << (int)i << " (table is disabled by effil.allow_table_upvalues)";
|
|
||||||
}
|
|
||||||
|
|
||||||
StoredObject storedObject;
|
StoredObject storedObject;
|
||||||
try {
|
try {
|
||||||
|
const auto& upvalue = sol::stack::pop<sol::object>(state);
|
||||||
storedObject = createStoredObject(upvalue);
|
storedObject = createStoredObject(upvalue);
|
||||||
assert(storedObject.get() != nullptr);
|
assert(storedObject.get() != nullptr);
|
||||||
}
|
}
|
||||||
@ -87,8 +64,8 @@ sol::object Function::loadFunction(lua_State* state) {
|
|||||||
for(size_t i = 0; i < ctx_->upvalues.size(); ++i) {
|
for(size_t i = 0; i < ctx_->upvalues.size(); ++i) {
|
||||||
#if LUA_VERSION_NUM > 501
|
#if LUA_VERSION_NUM > 501
|
||||||
if (ctx_->envUpvaluePos == i + 1) {
|
if (ctx_->envUpvaluePos == i + 1) {
|
||||||
lua_rawgeti(state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); // push _ENV to stack
|
lua_pushglobaltable(state); // push _G to stack
|
||||||
lua_setupvalue(state, -2, i + 1); // pop _ENV and set as upvalue
|
lua_setupvalue(state, -2, i + 1); // pop _G and set as upvalue
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif // LUA_VERSION_NUM > 501
|
#endif // LUA_VERSION_NUM > 501
|
||||||
|
|||||||
@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
sol::object luaAllowTableUpvalues(sol::this_state state, const sol::stack_object&);
|
|
||||||
|
|
||||||
class FunctionData : public GCData {
|
class FunctionData : public GCData {
|
||||||
public:
|
public:
|
||||||
std::string function;
|
std::string function;
|
||||||
|
|||||||
@ -107,7 +107,6 @@ int luaopen_effil(lua_State* L) {
|
|||||||
"pairs", SharedTable::globalLuaPairs,
|
"pairs", SharedTable::globalLuaPairs,
|
||||||
"ipairs", SharedTable::globalLuaIPairs,
|
"ipairs", SharedTable::globalLuaIPairs,
|
||||||
"size", luaSize,
|
"size", luaSize,
|
||||||
"allow_table_upvalues", luaAllowTableUpvalues,
|
|
||||||
"hardware_threads", std::thread::hardware_concurrency,
|
"hardware_threads", std::thread::hardware_concurrency,
|
||||||
sol::meta_function::index, luaIndex
|
sol::meta_function::index, luaIndex
|
||||||
);
|
);
|
||||||
|
|||||||
@ -122,11 +122,6 @@ local function generate_tests()
|
|||||||
-- effil.gc.step
|
-- effil.gc.step
|
||||||
test.type_mismatch.input_types_mismatch_p(1, "number", "gc.step", type_instance)
|
test.type_mismatch.input_types_mismatch_p(1, "number", "gc.step", type_instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
if typename ~= "boolean" then
|
|
||||||
-- effil.allow_table_upvalue
|
|
||||||
test.type_mismatch.input_types_mismatch_p(1, "boolean", "allow_table_upvalues", type_instance)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Below presented tests which support everything except coroutines
|
-- Below presented tests which support everything except coroutines
|
||||||
@ -155,6 +150,5 @@ end
|
|||||||
generate_tests()
|
generate_tests()
|
||||||
|
|
||||||
test.type_mismatch.gc_checks_after_tests = function()
|
test.type_mismatch.gc_checks_after_tests = function()
|
||||||
effil.allow_table_upvalues(true)
|
|
||||||
default_tear_down()
|
default_tear_down()
|
||||||
end
|
end
|
||||||
@ -60,7 +60,7 @@ test.upvalues.check_table = function()
|
|||||||
test.equal(ret, "effil.table: value")
|
test.equal(ret, "effil.table: value")
|
||||||
end
|
end
|
||||||
|
|
||||||
test.upvalues.check_env = function()
|
test.upvalues.check_global_env = function()
|
||||||
local obj1 = 13 -- local
|
local obj1 = 13 -- local
|
||||||
obj2 = { key = "origin" } -- global
|
obj2 = { key = "origin" } -- global
|
||||||
local obj3 = 79 -- local
|
local obj3 = 79 -- local
|
||||||
@ -81,39 +81,19 @@ test.upvalues.check_env = function()
|
|||||||
test.equal(ret, "13, local, 79")
|
test.equal(ret, "13, local, 79")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function check_works(should_work)
|
if LUA_VERSION > 51 then
|
||||||
local obj = { key = "value"}
|
|
||||||
local function worker()
|
|
||||||
return obj.key
|
|
||||||
end
|
|
||||||
|
|
||||||
local ret, err = pcall(effil.thread(worker))
|
test.upvalues.check_custom_env = function()
|
||||||
if ret then
|
local function create_foo()
|
||||||
err:wait()
|
local _ENV = { key = 'value' }
|
||||||
end
|
return function()
|
||||||
test.equal(ret, should_work)
|
return key
|
||||||
if not should_work then
|
|
||||||
test.equal(err, "effil.thread: bad function upvalue #1 (table is disabled by effil.allow_table_upvalues)")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test.upvalues_table.tear_down = function()
|
local foo = create_foo()
|
||||||
effil.allow_table_upvalues(true)
|
local ret = effil.thread(foo)():get()
|
||||||
default_tear_down()
|
test.equal(ret, 'value')
|
||||||
end
|
end
|
||||||
|
|
||||||
test.upvalues_table.disabling_table_upvalues = function()
|
end -- LUA_VERSION > 51
|
||||||
test.equal(effil.allow_table_upvalues(), true)
|
|
||||||
-- works by default
|
|
||||||
check_works(true)
|
|
||||||
|
|
||||||
-- disable
|
|
||||||
test.equal(effil.allow_table_upvalues(false), true)
|
|
||||||
check_works(false)
|
|
||||||
test.equal(effil.allow_table_upvalues(), false)
|
|
||||||
|
|
||||||
-- enable back
|
|
||||||
test.equal(effil.allow_table_upvalues(true), false)
|
|
||||||
check_works(true)
|
|
||||||
test.equal(effil.allow_table_upvalues(), true)
|
|
||||||
end
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user