From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 8F2A857B70E; Tue, 5 Sep 2023 17:15:00 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 8F2A857B70E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1693923300; bh=95HvkBWDOGIODAED7DYwogZsIotQuDkEYXczrEpGfa4=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=fM5vY74e41LODOD/jC6ojc6IjpKk4Tgo11Q2HEo2uQmPZ/mO61EAkiZg4GFbfhQ+f jO4dn978dxptLRmbaW4qUrXqyLpOEy5a4ihmb84W6P24ixHvsTwmics4Rmx4wYf9cQ h2Z+DxkUEDSolNRam+JWFo3wkFY+rkEQuTP8zBSs= Received: from smtpng3.i.mail.ru (smtpng3.i.mail.ru [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id BA79857B70E for ; Tue, 5 Sep 2023 17:14:58 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org BA79857B70E Received: by smtpng3.m.smailru.net with esmtpa (envelope-from ) id 1qdWpV-0004xp-SU; Tue, 05 Sep 2023 17:14:58 +0300 Date: Tue, 5 Sep 2023 17:10:14 +0300 To: Sergey Bronnikov Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD96E142CFC92DB15CD90AAA51E9363FBE6A21DF977184D824F182A05F53808504049665DDFEE162788F6A4A1AB4B69A49F377E7DB208B0AB4848625E9497AAE90B X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE752E71F0C64B7C834EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637E8D1333770DC60CDEA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BE5CCB53A13BC8DBA8DB4A03DF029F31D85D4F5A05E82D24BCC7F00164DA146DAFE8445B8C89999728AA50765F7900637CBDA538BD653CEDD389733CBF5DBD5E9C8A9BA7A39EFB766F5D81C698A659EA7CC7F00164DA146DA9985D098DBDEAEC8989FD0BDF65E50FBF6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA7E827F84554CEF5019E625A9149C048EE33AC447995A7AD181150BA43C84913FC3A03B725D353964B1D471462564A2E1935872C767BF85DA227C277FBC8AE2E8B696E4123C2B4120575ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: 0D63561A33F958A50369EE6E896E10F1B251013FABA5FA9D09A95FF247870064F87CCE6106E1FC07E67D4AC08A07B9B0E753FA5741D1AD02CB5012B2E24CD356 X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF3FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF52B9BDF251ABEDE43D624A5649693DBB0AC9004B653C30A52A4759A5A3F7FF9E14755E582FAB3B35EA61C66FA002EE27D8F83D9EAC621E8C81460AF7390E952BA74DFFEFA5DC0E7F02C26D483E81D6BE5EF9655DD6DEA7D65774BB76CC95456EEC5B5AD62611EEC62B5AFB4261A09AF0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj3VBHtC3oXrPbhiwpQJRimg== X-DA7885C5: 35B07F83BD59D781C84A3DC0C4B9721DDDC3EA51786EB052B0A033F5540EF7C7262E2D401490A4A0DB037EFA58388B346E8BC1A9835FDE71 X-Mailru-Sender: 689FA8AB762F73930F533AC2B33E986BEF6C0BAF1381F69510EF7E4DE49FE75E0FBE9A32752B8C9C2AA642CC12EC09F1FB559BB5D741EB962F61BD320559CF1EFD657A8799238ED55FEEDEB644C299C0ED14614B50AE0675 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH luajit 1/2][v2] Fix embedded bytecode loader. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: max.kokryashkin@gmail.com, tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Hi, Sergey! Thanks for the patch! Please, consider my comments below. On 31.08.23, Sergey Bronnikov wrote: > From: Sergey Bronnikov > > (cherry-picked from commit 820339960123dc78a7ce03edf53fcf4fdae0e55d) > > The original problem is specific to x32 and is as follows: when a chunk > with a bytecode library is loaded into memory, and the address is higher > than 0x80000100, the `LexState->pe`, that contains an address of the end > of the bytecode chunk in the memory, will wrap around and become smaller > than the address in `LexState->p`, that contains an address of the > beginning of bytecode chunk in the memory. In `bcread_fill()` called by > `bcread_want()`, `memcpy()` is called with a very large size and causes > bus error on x86 and segmentation fault on ARM Android. Typo: s/bus error/the bus error/ Typo: s/segmentation fault/the segmentation fault/ > > The problem cannot be reproduced on platforms supported by Tarantool > (ARM64, x86_64), so test doesn't reproduce a problem without a patch and > tests the patch partially. > > Sergey Bronnikov: > * added the description and the test > --- > src/lib_package.c | 4 +- > src/lj_bcread.c | 10 +- > src/lj_lex.c | 6 ++ > src/lj_lex.h | 1 + > .../lj-549-bytecode-loader.test.lua | 96 +++++++++++++++++++ > 5 files changed, 110 insertions(+), 7 deletions(-) > create mode 100644 test/tarantool-tests/lj-549-bytecode-loader.test.lua > > diff --git a/test/tarantool-tests/lj-549-bytecode-loader.test.lua b/test/tarantool-tests/lj-549-bytecode-loader.test.lua > new file mode 100644 > index 00000000..889be80a > --- /dev/null > +++ b/test/tarantool-tests/lj-549-bytecode-loader.test.lua > @@ -0,0 +1,96 @@ > +local tap = require('tap') > +local ffi = require('ffi') > +local utils = require('utils') > +local test = tap.test('lj-549-bytecode-loader'):skipcond({ > + -- ['Test requires GC64 mode enabled'] = not require('ffi').abi('gc64'), > +}) Minor: It's better to require ffi and utils after test initialization via `tap.test()`, see other tests for example. Also, I suppose that we don't need `utils` itself, but `utils.exec.makecmd`. > + > +test:plan(1) > + > +-- Test creates a shared library with LuaJIT bytecode, > +-- loads shared library as a Lua module and checks, > +-- that no crashes eliminated. > +-- > +-- $ make HOST_CC='gcc -m32' TARGET_CFLAGS='-m32' \ > +-- TARGET_LDFLAGS='-m32' \ > +-- TARGET_SHLDFLAGS='-m32' \ > +-- -f Makefile.original > +-- $ echo 'print("test")' > a.lua > +-- $ LUA_PATH="src/?.lua;;" luajit -b a.lua a.c > +-- $ gcc -m32 -fPIC -shared a.c -o a.so > +-- $ luajit -e "require('a')" > +-- Program received signal SIGBUS, Bus error > + > +local function file_exists(fname) > + return io.open(fname, 'r') or true and false OK, this is a little bit confusing: If file doesn't exists we go to `or true` and after check `and false` which is always false. Tricky, but works. Also, here we don't close file handler. I suggest it is better to rewrite this as the following: | local fh = io.open(name, 'r') | return fh and io.close(fh) It is simplier to read, and fixes problem with leaking handler. > +end > + > +local function get_file_name(file) > + return file:match("[^/]*$") Minor: it may match the empty string for a directory occasionally: | src/luajit -e 'print([["]]..("/tmp/"):match("[^/]*$")..[["]])' | "" Nit: use single quotes instead of double quotes if possible. Nit: `[^/\\]` is better since it also covers Windows. See | local dirname = arg[0]:gsub('([^/\\]+)$', '') Since we don't support Windows feel free to ignore. > +end > + > +local stdout_msg = 'Lango team' > +local lua_code = ('print(%q)'):format(stdout_msg) > +local fpath = os.tmpname() > +local path_lua = ('%s.lua'):format(fpath) > +local path_c = ('%s.c'):format(fpath) > +local path_so = ('%s.so'):format(fpath) Minor: I suppose it should be renamed to `path_shared`, since on macOS they have the ".dyld" suffix for shared libs. Hence, we need to use the suffix in format of the shared library name too. You may take some inspiration from here [1]. > + > +-- Create a file with a minimal Lua code. > +local fh = assert(io.open(path_lua, 'w')) > +fh:write(lua_code) > +fh:close() > + > +local module_name = assert(get_file_name(fpath)) > + > +local basedir = function(path) > + local sep = '/' Why do we need an additional variable here? Nit: Indent is 4 spaces instead of 2. > + return path:match('(.*' .. sep .. ')') or './' It's better to mention that the pattern matching is greedy, so we match until the last separator. > +end > + > +-- Create a C file with LuaJIT bytecode. > +-- We cannot use utils.makecmd, because command-line generated > +-- by `makecmd` contains `-e` that is incompatible with option `-b`. Nit: comment line width is more than 66 symbols > +local function create_c_file(pathlua, pathc) > + local lua_path = os.getenv('LUA_PATH') > + local lua_bin = require('utils').exec.luacmd(arg):match('%S+') > + local cmd_fmt = 'LUA_PATH="%s" %s -b %s %s' > + local cmd = (cmd_fmt):format(lua_path, lua_bin, pathlua, pathc) > + local ret = os.execute(cmd) > + assert(ret == 0, 'create a C file with bytecode') > +end > + > +create_c_file(path_lua, path_c) > +assert(file_exists(path_c)) Minor: The test flow is a little bit hard to read due to function declarations. Maybe it is better to declare all utility functions first and then use them one by one? This makes control flow easier to read. > + > +-- Compile C source code with LuaJIT bytecode to a shared library. > +-- `-m64` is not available on ARM64, see > +-- "3.18.1 AArch64 Options in the manual", > +-- https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html > +local cflags_64 = jit.arch == 'arm64' and '-march=armv8-a' or '-m64' > +local cflags = ffi.abi('32bit') and '-m32' or cflags_64 > +local cc_cmd = ('cc %s -fPIC -shared %s -o %s'):format(cflags, path_c, path_so) > +local ph = io.popen(cc_cmd) > +ph:close() > +assert(file_exists(path_so)) > + > +-- Load shared library as a Lua module. > +local lua_cpath = ('"/tmp/?.so;"'):format(basedir(fpath)) > +assert(file_exists(path_so)) > +local cmd = utils.exec.makecmd(arg, { > + script = ('-e "require([[%s]])"'):format(module_name), Nit: Indent is 4 spaces instead of 2. > + env = { > + LUA_CPATH = lua_cpath, Nit: Indent is 4 spaces instead of 2. > + -- It is required to cleanup LUA_PATH, otherwise > + -- LuaJIT loads Lua module, see tarantool-tests/utils/init.lua. Nit: comment line width is more than 66 symbols Actually I don't understand from the comment what Lua module exactly is loaded. Maybe it's better to fix this behaviour? Feel free to ignore. > + LUA_PATH = '', > + }, > +}) > +local res = cmd() > +test:ok(res == stdout_msg, 'bytecode loader works') > + > +os.remove(path_lua) > +os.remove(path_c) > +os.remove(path_so) > + > +os.exit(test:check() and 0 or 1) > -- > 2.34.1 > [1]: https://github.com/tarantool/tarantool/blob/dc8973c3de6311ab11df8d43520e1d40de4b9c7b/test/box/func_reload.test.lua#L5 -- Best regards, Sergey Kaplun