lgi-devs / lgi

Dynamic Lua binding to GObject libraries using GObject-Introspection
MIT License
440 stars 70 forks source link

Memory corruption with g_spawn_async_with_pipes #245

Open fstirlitz opened 4 years ago

fstirlitz commented 4 years ago

Version 0.9.2-2+b1 (Debian package), reproduces on Lua 5.1, 5.2 and 5.3. Host architecture is i686.

Sample code:

local GLib = require('lgi').GLib
local N = 1000000

local envp = {}
for i = 1, N do
    envp[#envp + 1] = ('VAR%u=%u'):format(i, i)
end

GLib.spawn_async_with_pipes('.', { '/bin/true' }, envp, { }, nil)

Depending on the value of N and the Lua version, this may corrupt the heap and fail an assertion on subsequent realloc or crash immediately.

fstirlitz commented 4 years ago

Okay, I think I got it. This is unfortunately a design issue.

In the lgi core there is a function lgi_guard_create, which creates a guard object whose sole purpose is to call the destructor of some object if the Lua stack is unwound. Each guard object occupies a separate stack slot. However, (PUC-Rio) Lua puts a rather small limit on the number of stack slots. Attempting to marshal an array of a million strings exceeds that limit easily. And indeed when I put g_assert (lua_checkstack (L, 2)) at the beginning of lgi_guard_create, I get an assertion failure instead of memory corruption.

But in any case, even though I debugged this, it seems this wasn’t actually the source of my original issue from which this was reduced (though it may have been a contributing factor), because the issue disappears when I simply replace the distro-installed copy of corelgilua51.so with a copy built from the latest git master without any meaningful fixes applied. So consider this report my rejoinder to issue #225.