diff --git a/CodeGen/src/NativeState.h b/CodeGen/src/NativeState.h index 941db252..7b42deb8 100644 --- a/CodeGen/src/NativeState.h +++ b/CodeGen/src/NativeState.h @@ -49,7 +49,7 @@ struct NativeContext int (*luaH_getn)(Table* t) = nullptr; Table* (*luaH_new)(lua_State* L, int narray, int lnhash) = nullptr; - Table* (*luaH_clone)(lua_State* L, Table* tt) = nullptr; + Table* (*luaH_clone)(lua_State* L, Table* tt, bool raw) = nullptr; void (*luaH_resizearray)(lua_State* L, Table* t, int nasize) = nullptr; TValue* (*luaH_setnum)(lua_State* L, Table* t, int key); diff --git a/VM/src/ltable.cpp b/VM/src/ltable.cpp index dafb2b3f..3be917e4 100644 --- a/VM/src/ltable.cpp +++ b/VM/src/ltable.cpp @@ -793,11 +793,10 @@ int luaH_getn(Table* t) } } -Table* luaH_clone(lua_State* L, Table* tt) +Table* luaH_clone(lua_State* L, Table* tt, bool raw) { Table* t = luaM_newgco(L, Table, sizeof(Table), L->activememcat); luaC_init(L, t, LUA_TTABLE); - t->metatable = tt->metatable; t->tmcache = tt->tmcache; t->array = NULL; t->sizearray = 0; @@ -808,6 +807,9 @@ Table* luaH_clone(lua_State* L, Table* tt) t->node = cast_to(LuaNode*, dummynode); t->lastfree = 0; + if (!raw) // Prevent unauthorized assigning of locked metatables + t->metatable = tt->metatable; + if (tt->sizearray) { t->array = luaM_newarray(L, tt->sizearray, TValue, t->memcat); diff --git a/VM/src/ltable.h b/VM/src/ltable.h index 021f21bf..0c0690ce 100644 --- a/VM/src/ltable.h +++ b/VM/src/ltable.h @@ -27,7 +27,7 @@ LUAI_FUNC void luaH_resizehash(lua_State* L, Table* t, int nhsize); LUAI_FUNC void luaH_free(lua_State* L, Table* t, struct lua_Page* page); LUAI_FUNC int luaH_next(lua_State* L, Table* t, StkId key); LUAI_FUNC int luaH_getn(Table* t); -LUAI_FUNC Table* luaH_clone(lua_State* L, Table* tt); +LUAI_FUNC Table* luaH_clone(lua_State* L, Table* tt, bool raw); LUAI_FUNC void luaH_clear(Table* tt); #define luaH_setslot(L, t, slot, key) (invalidateTMcache(t), (slot == luaO_nilobject ? luaH_newkey(L, t, key) : cast_to(TValue*, slot))) diff --git a/VM/src/ltablib.cpp b/VM/src/ltablib.cpp index 75d9f400..6e6c9216 100644 --- a/VM/src/ltablib.cpp +++ b/VM/src/ltablib.cpp @@ -585,10 +585,7 @@ static int tisfrozen(lua_State* L) static int tclone(lua_State* L) { luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, !luaL_getmetafield(L, 1, "__metatable"), 1, "table has a protected metatable"); - - Table* tt = luaH_clone(L, hvalue(L->base)); - + Table* tt = luaH_clone(L, hvalue(L->base), luaL_getmetafield(L, 1, "__metatable") ? true : false); TValue v; sethvalue(L, &v, tt); luaA_pushobject(L, &v);