Keep all Lua symbols in unsafe mode to load C modules

This commit is contained in:
Alex Orlenko 2021-06-12 18:00:55 +01:00
parent 0fe898c0dd
commit 3b9d8a7b5f
5 changed files with 334 additions and 2 deletions

View File

@ -245,7 +245,10 @@ fn main() {
.define("COMPAT53_INCLUDE_SOURCE", None); .define("COMPAT53_INCLUDE_SOURCE", None);
#[cfg(feature = "luajit")] #[cfg(feature = "luajit")]
shim_cc.define("COMPAT53_LUAJIT", None); shim_cc.define("COMPAT53_LUAJIT", None);
shim_cc.file("src/ffi/shim/shim.c").compile("shim"); shim_cc
.file("src/ffi/shim/shim.c")
.file("src/ffi/shim/symbols.c")
.compile("shim");
println!("cargo:rerun-if-changed=src/ffi/shim"); println!("cargo:rerun-if-changed=src/ffi/shim");
println!("cargo:rerun-if-changed=build"); println!("cargo:rerun-if-changed=build");

View File

@ -280,6 +280,9 @@ pub const SYS_MIN_ALIGN: usize = 8;
)))] )))]
pub const SYS_MIN_ALIGN: usize = 16; pub const SYS_MIN_ALIGN: usize = 16;
// Re-rexport all symbols
pub use symbols::keep_lua_symbols;
#[allow(unused_imports, dead_code, non_camel_case_types)] #[allow(unused_imports, dead_code, non_camel_case_types)]
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
mod glue { mod glue {
@ -293,5 +296,6 @@ mod lauxlib;
mod lua; mod lua;
mod luaconf; mod luaconf;
mod lualib; mod lualib;
mod symbols;
pub mod safe; pub mod safe;

310
src/ffi/shim/symbols.c Normal file
View File

@ -0,0 +1,310 @@
// The MIT License (MIT)
//
// Copyright (c) 2019-2021 A. Orlenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
void *LUA_ALL_SYMBOLS[] = {
/*
* lua.h
*/
lua_newstate,
lua_close,
lua_newthread,
lua_atpanic,
#if LUA_VERSION_NUM > 501
lua_version,
#endif
#if LUA_VERSION_NUM > 503
lua_resetthread,
#endif
#ifdef HAVE_LUA_RESETTHREAD
lua_resetthread,
#endif
#if LUA_VERSION_NUM > 501
lua_absindex,
#endif
lua_gettop,
lua_settop,
lua_pushvalue,
#if LUA_VERSION_NUM > 502
lua_rotate,
#else
lua_remove,
lua_insert,
lua_replace,
#endif
#if LUA_VERSION_NUM > 501
lua_copy,
#endif
lua_checkstack,
lua_xmove,
lua_isnumber,
lua_isstring,
lua_iscfunction,
lua_isuserdata,
lua_type,
lua_typename,
#if LUA_VERSION_NUM == 501
lua_tonumber,
lua_tointeger,
#else
lua_tonumberx,
lua_tointegerx,
#endif
#if LUA_VERSION_NUM == 502
lua_tounsignedx,
#endif
lua_toboolean,
lua_tolstring,
#if LUA_VERSION_NUM == 501
lua_objlen,
#else
lua_rawlen,
#endif
lua_tocfunction,
lua_touserdata,
lua_tothread,
lua_topointer,
#if LUA_VERSION_NUM == 501
lua_equal,
lua_lessthan,
#else
lua_arith,
lua_compare,
#endif
lua_rawequal,
lua_pushnil,
lua_pushnumber,
lua_pushinteger,
#if LUA_VERSION_NUM == 502
lua_pushunsigned,
#endif
lua_pushlstring,
lua_pushstring,
lua_pushvfstring,
lua_pushfstring,
lua_pushcclosure,
lua_pushboolean,
lua_pushlightuserdata,
lua_pushthread,
#if LUA_VERSION_NUM > 501
lua_getglobal,
lua_rawgetp,
#endif
#if LUA_VERSION_NUM > 503
lua_getiuservalue,
#elif LUA_VERSION_NUM > 501
lua_getuservalue,
#endif
lua_gettable,
lua_getfield,
#if LUA_VERSION_NUM > 502
lua_geti,
#endif
lua_rawget,
lua_rawgeti,
lua_createtable,
#if LUA_VERSION_NUM < 504
lua_newuserdata,
#else
lua_newuserdatauv,
#endif
#if LUA_VERSION_NUM == 501
lua_getfenv,
#endif
lua_getmetatable,
#if LUA_VERSION_NUM > 501
lua_setglobal,
lua_rawsetp,
#endif
#if LUA_VERSION_NUM > 503
lua_setiuservalue,
#elif LUA_VERSION_NUM > 501
lua_setuservalue,
#endif
lua_settable,
lua_setfield,
#if LUA_VERSION_NUM > 502
lua_seti,
#endif
lua_rawset,
lua_rawseti,
#if LUA_VERSION_NUM == 501
lua_setfenv,
#endif
lua_setmetatable,
#if LUA_VERSION_NUM > 501
lua_callk,
lua_pcallk,
#else
lua_call,
lua_pcall,
lua_cpcall,
#endif
#if LUA_VERSION_NUM == 502
lua_getctx,
#endif
lua_load,
lua_dump,
#if LUA_VERSION_NUM > 501
lua_yieldk,
#else
lua_yield,
#endif
lua_resume,
lua_status,
#if LUA_VERSION_NUM > 502
lua_isyieldable,
#endif
lua_gc,
lua_error,
lua_next,
lua_concat,
#if LUA_VERSION_NUM > 501
lua_len,
#endif
#if LUA_VERSION_NUM > 502
lua_stringtonumber,
#endif
lua_getallocf,
lua_setallocf,
lua_getstack,
lua_getinfo,
lua_getlocal,
lua_setlocal,
lua_getupvalue,
lua_setupvalue,
#if LUA_VERSION_NUM > 501
lua_upvalueid,
lua_upvaluejoin,
#endif
lua_sethook,
lua_gethook,
lua_gethookmask,
lua_gethookcount,
/*
* lauxlib.h
*/
#if LUA_VERSION_NUM > 501
luaL_checkversion_,
luaL_tolstring,
#else
luaL_register,
luaL_typerror,
#endif
#if LUA_VERSION_NUM == 502
luaL_checkunsigned,
luaL_optunsigned,
#endif
luaL_getmetafield,
luaL_callmeta,
luaL_argerror,
luaL_checklstring,
luaL_optlstring,
luaL_checknumber,
luaL_optnumber,
luaL_checkinteger,
luaL_optinteger,
luaL_checkstack,
luaL_checktype,
luaL_checkany,
luaL_newmetatable,
#if LUA_VERSION_NUM > 501
luaL_setmetatable,
luaL_testudata,
#endif
luaL_checkudata,
luaL_where,
luaL_error,
luaL_checkoption,
#if LUA_VERSION_NUM > 501
luaL_fileresult,
luaL_execresult,
luaL_loadfilex,
luaL_loadbufferx,
luaL_len,
luaL_setfuncs,
luaL_getsubtable,
luaL_traceback,
luaL_requiref,
#else
luaL_loadfile,
luaL_loadbuffer,
luaL_findtable,
#endif
luaL_ref,
luaL_unref,
luaL_loadstring,
luaL_newstate,
luaL_gsub,
luaL_buffinit,
#if LUA_VERSION_NUM > 501
luaL_prepbuffsize,
luaL_pushresultsize,
luaL_buffinitsize,
#else
luaL_prepbuffer,
#endif
luaL_addlstring,
luaL_addstring,
luaL_addvalue,
luaL_pushresult,
/*
* lualib.h
*/
luaopen_base,
#if LUA_VERSION_NUM > 501
luaopen_coroutine,
#endif
luaopen_table,
luaopen_io,
luaopen_os,
luaopen_string,
#if LUA_VERSION_NUM > 502
luaopen_utf8,
#endif
#if LUA_VERSION_NUM == 502
luaopen_bit32,
#endif
luaopen_math,
luaopen_debug,
luaopen_package,
luaL_openlibs,
};

10
src/ffi/symbols.rs Normal file
View File

@ -0,0 +1,10 @@
use std::ffi::c_void;
extern "C" {
static LUA_ALL_SYMBOLS: *const c_void;
}
// Hack to avoid stripping unused Lua symbols from binary in order to load C modules
pub fn keep_lua_symbols() {
assert_ne!(format!("{:p}", unsafe { LUA_ALL_SYMBOLS }), "");
}

View File

@ -233,7 +233,7 @@ impl Lua {
} }
} }
let mut lua = unsafe { Self::unsafe_new_with(libs, options) }; let mut lua = unsafe { Self::inner_new(libs, options) };
if libs.contains(StdLib::PACKAGE) { if libs.contains(StdLib::PACKAGE) {
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules"); mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
@ -253,6 +253,11 @@ impl Lua {
/// ///
/// [`StdLib`]: struct.StdLib.html /// [`StdLib`]: struct.StdLib.html
pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua { pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
ffi::keep_lua_symbols();
Self::inner_new(libs, options)
}
unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
#[cfg_attr(any(feature = "lua51", feature = "luajit"), allow(dead_code))] #[cfg_attr(any(feature = "lua51", feature = "luajit"), allow(dead_code))]
unsafe extern "C" fn allocator( unsafe extern "C" fn allocator(
extra_data: *mut c_void, extra_data: *mut c_void,