actboy168 / bee.lua

Lua runtime and toolset
MIT License
160 stars 30 forks source link

lua_error linux下是longjump, 会跳过调用cpp对象的析构函数。windows下也容易出现double free UB #39

Closed sniper00 closed 1 year ago

sniper00 commented 1 year ago

https://github.com/actboy168/bee.lua/blob/master/binding/lua_filesystem.cpp#L122

sniper00 commented 1 year ago

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/longjmp?view=msvc-170

Microsoft Specific

In Microsoft C++ code on Windows, longjmp uses the same stack-unwinding semantics as exception-handling code. It is safe to use in the same places that C++ exceptions can be raised. However, this usage is not portable, and comes with some important caveats.

下面代码在windows平台会触发double free,估计是longjmp造成的undefined behavior

#include "lua.hpp"
#include <string>
struct xstring
{
    std::string data_;

    xstring(std::string&& d)
        :data_(std::move(d))
    {
        printf("object create: %p\n", this);
    }

    ~xstring()
    {
        printf("object delete: %p\n", this);
    }

    void append(std::string&& str)
    {
        data_.append(std::move(str));
    }

    const char* data() const
    {
        return data_.data();
    }
};

int main(int, char* []) {
    auto L = luaL_newstate();

    auto protect_init = [](lua_State* L) -> int {
        luaL_openlibs(L);

        int r = LUA_OK;

        {
            xstring initialize = std::string("bad");
            initialize.append("hello");
            r = luaL_dostring(L, initialize.data());
        }//let object destruct

        if (r != LUA_OK)
        {
            return luaL_error(L, "initialize");
        }
        return 0;
    };

    lua_pushcfunction(L, protect_init);
    if (lua_pcall(L, 0, 0, 0) != LUA_OK)
    {
        printf("error: %s\n", lua_tostring(L, -1));
        return -1;
    }
    return 0;
}
actboy168 commented 1 year ago

严格来说确实是个问题,不过我的lua_error向来等价于abort,所以不是很有所谓。

actboy168 commented 1 year ago

将lua编译为c++可以解决这个问题。如果只是使用bee,我认为这个改动是安全的。但是如果使用了bee和其他c++代码,这个改动可能是巨大的。

sniper00 commented 1 year ago

编译成Cpp,会造成性能下降,如果你大量用Lua 协程的话

actboy168 commented 1 year ago

嗯,经过一些测试,在有些平台上c++异常不能安全地穿越c的栈帧。不值得为这个还不是问题的问题,大费周章。