Skip to content

Commit

Permalink
Experiments in lj-881-fix-lua-concat.test.c [TMP]
Browse files Browse the repository at this point in the history
https://github.com/tarantool/luajit/actions/runs/12831238829/job/35781196235

 =================================================================
==765154==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 256 byte(s) in 1 object(s) allocated from:
    #0 0x496949 in realloc (/opt/actions-runner/_work/_temp/build-12831238829/test/tarantool-c-tests/lj-881-fix-lua-concat.c_test+0x496949)
    #1 0x4da87a in lj_mem_realloc /opt/actions-runner/_work/luajit/luajit/src/lj_gc.c:869:7
    #2 0x53f2a8 in lj_ir_growtop /opt/actions-runner/_work/luajit/luajit/src/lj_ir.c:81:23
    #3 0x53f5f1 in lj_ir_nextins /opt/actions-runner/_work/luajit/luajit/src/lj_iropt.h:34:40
    #4 0x53f5f1 in lj_ir_emit /opt/actions-runner/_work/luajit/luajit/src/lj_ir.c:118:15
    #5 0x5cc2ea in lj_record_setup /opt/actions-runner/_work/luajit/luajit/src/lj_record.c:2651:3
    #6 0x5440f0 in trace_state /opt/actions-runner/_work/luajit/luajit/src/lj_trace.c:681:7
    #7 0x58c045 in lj_vm_cpcall /opt/actions-runner/_work/_temp/build-12831238829/src/lj_vm.S:1262

SUMMARY: AddressSanitizer: 256 byte(s) leaked in 1 allocation(s).
  • Loading branch information
ligurio committed Jan 17, 2025
1 parent 7598548 commit 8b392ec
Showing 1 changed file with 53 additions and 72 deletions.
125 changes: 53 additions & 72 deletions test/tarantool-c-tests/lj-881-fix-lua-concat.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,93 +6,74 @@
#include "test.h"
#include "utils.h"

/*
* This test demonstrates LuaJIT's incorrect behaviour when
* calling `lua_concat()` with userdata with the __concat metamethod.
* See https://github.com/LuaJIT/LuaJIT/issues/881 for details.
*/

#define TYPE_NAME "int"

#define TEST_VALUE 100
#define TOSTR(s) #s
#define CONCAT(A, B) A TOSTR(B)
static int bbb(lua_State *L) {
luaL_dostring(L, "local function varg_func(...) end return function() return varg_func() end");
luaL_dostring(L, "repeat until nil > 1");
return 0;
}

static int __concat(lua_State *L)
{
const char *s = luaL_checkstring(L, 1);
int *n = (int *)luaL_checkudata(L, 2, TYPE_NAME);
/* Do non-default concatenation. */
lua_pushfstring(L, "%s + %d", s, *n);
static int aaa(lua_State *L) {
(void)L;
luaL_dostring(L, "local function varg_func(...) end return function() return varg_func() end");
lua_pushcfunction(L, (lua_CFunction)bbb);
lua_pcall(L, 0, 0, 0);
luaL_dostring(L, "local function varg_func(...) end return function() return varg_func() end");
return 1;
}

static const luaL_Reg mt[] = {
{ "__concat", __concat },
{ NULL, NULL}
};

static int lua_concat_testcase(void *test_state)
static void jit_attach(lua_State *L, void *cb, const char *event)
{
/* Setup. */
lua_State *L = test_state;
const int top = 4;

/* Create metatable and put it to the Lua registry. */
luaL_newmetatable(L, TYPE_NAME);
/* Fill metatable. */
luaL_register(L, 0, mt);
lua_pop(L, 1);
lua_getglobal(L, "jit");
lua_getfield(L, -1, "attach");
lua_pushcfunction(L, (lua_CFunction)cb);
if (event != NULL) {
lua_pushstring(L, event);
} else {
lua_pushnil(L);
}
lua_pcall(L, 2, 0, 0);
}

assert_int_equal(lua_gettop(L), 0);
static int trace_cb(lua_State *L) {
(void)L;
/* is_cb_called = 1; */
/* luaL_dostring(L, "repeat until nil > 1"); */
/* luaL_dostring(L, "local function varg_func(...) end return function() return varg_func() end"); */
/* luaL_dostring(L, "error()"); */
lua_pushcfunction(L, (lua_CFunction)aaa);
lua_pcall(L, 0, 0, 0);
return 0;
}

lua_pushliteral(L, "C");
lua_pushliteral(L, "B");
lua_pushliteral(L, "A");
int main(void)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, "jit.opt.start('hotloop=1')");

int *n = (int *)lua_newuserdata(L, sizeof(*n));
*n = 100;
jit_attach(L, (void *)trace_cb, "trace");

luaL_getmetatable(L, TYPE_NAME);
lua_setmetatable(L, -2);
/* Frame with a broken Lua code. */
luaL_dostring(L, "repeat until nil > 1");
/* luaL_dostring(L, "local function varg_func(...) end return function() return varg_func() end"); */

assert_int_equal(lua_gettop(L), top);
/* Frame with C function. */
/* lua_getfield(L, LUA_GLOBALSINDEX, "print"); */
/* lua_pcall(L, 0, 0, 0); */

/* Test body. */
/* lua_pushcfunction(L, (lua_CFunction)aaa); */
/* lua_pcall(L, 0, 0, 0); */

/*
* void lua_concat (lua_State *L, int n);
*
* Concatenates the n values at the top of the stack,
* pops them, and leaves the result at the top. If n is 1,
* the result is the single value on the stack; if n is 0,
* the result is the empty string [1].
*
* 1. https://www.lua.org/manual/5.1/manual.html
*/
/* lua_pushcfunction(L, (lua_CFunction)bbb); */
/* lua_pushcfunction(L, (lua_CFunction)aaa); */
/* lua_pcall(L, 0, 0, -2); */

/* Concatenate two elements on the top. */
lua_concat(L, 2);
jit_attach(L, (void *)trace_cb, NULL);

const char *str = lua_tostring(L, -1);
assert_int_equal(lua_gettop(L), top - 2 + 1);
const char expected_str[] = CONCAT("A + ", TEST_VALUE);
assert_str_equal(str, expected_str);
lua_State *LL = utils_lua_init();
utils_lua_close(LL);

/* Teardown. */
lua_settop(L, 0);

return TEST_EXIT_SUCCESS;
}

int main(void)
{
lua_State *L = utils_lua_init();
const struct test_unit tgroup[] = {
test_unit_def(lua_concat_testcase),
};
const int test_result = test_run_group(tgroup, L);
utils_lua_close(L);

return test_result;
return 0;
}

0 comments on commit 8b392ec

Please sign in to comment.