Re: Workarounds for LuaJIT's 4GB limit

  • From: Florian Weimer <fw@xxxxxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Tue, 21 Oct 2014 13:59:06 +0200

* Alex Wilson:

> On 16/10/14 09:30, Alex wrote:
>> The 4GB limit only applies to Lua objects and cdata allocated with
>> ffi.new or from ffi.typeof constructors. If you use malloc directly (via
>> declaring it with ffi.cdef then using it with ffi.C.malloc), you can use
>> memory outside of the limit.
>
> There is another limit as well that applies to lightuserdata pointers -- 
> I run into this a lot on Solaris and BSD variants where the stack is
> allocated all the way up near the top of memory. On these platforms
> you can't create a lightuserdata from something that's on the stack,
> or allocated up high in the address space in general. This regularly
> crashes LPEG and sometimes very recent versions of nginx-lua.

I cannot reproduce this, using:

#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>

static int
l_tolud(lua_State *L)
{
  lua_Integer a = lua_tointeger(L, 1);
  lua_Integer b = lua_tointeger(L, 2);
  unsigned au = a;
  unsigned bu = b;
  unsigned long long ap = au;
  unsigned long long bp = bu;
  unsigned long long combined = (ap << 32) | bp;
  lua_pushlightuserdata(L, (void *) combined);
  return 1;
}

int
luaopen_tolud(lua_State *L)
{
  struct luaL_Reg funcs[] = {
    {"tolud", l_tolud},
    {NULL, NULL},
  };
  lua_newtable(L);
  luaL_register(L, NULL, funcs);
  return 1;
}

//////////////////////////////////////////////////////////////////////

local tolud = (require "tolud").tolud
local ffi = require "ffi"

local values = {
   {0, 0},
   {0, 1},
   {1, 0},
   {0x7fff, 0xffffffff},
   {0x8000, 0},
}

for i = 1, #values do
   local val = values[i]
   local lud = tolud(val[1], val[2])
   print(val[1], val[2], lud)
end

----------------------------------------------------------------------

This program prints for me:

0       0       userdata: NULL
0       1       userdata: 0x00000001
1       0       userdata: 0x0100000000
32767   4294967295      userdata: 0x7fffffffffff
luajit: bad light userdata pointer
stack traceback:
        [C]: in function 'tolud'
        tolud_test.lua:14: in main chunk
        [C]: at 0x00405320

From this, I infer that all valid userspace pointers on x86_64 are
representable as lightuserdata values.  So you must be observing
another issue.

Other related posts: