<HTML><BODY><div class="cl-kg1tvl8zu1">Hi, Sergey! Thanks for the patch! LGTM<br> <div data-signature-widget="container"><div data-signature-widget="content"><div>--<br>Best regards,</div><div>Evgeniy Temirgaleev</div></div></div><br><div class="mail-quote-collapse"><blockquote style="border-left:1px solid #0857A6;margin:10px;padding:0 0 0 10px"><span>From: Sergey Kaplun <<a href="mailto:skaplun@tarantool.org">skaplun@tarantool.org</a>><br>To: Sergey Bronnikov <<a href="mailto:sergeyb@tarantool.org">sergeyb@tarantool.org</a>>, Evgeniy Temirgaleev <<a href="mailto:e.temirgaleev@tarantool.org">e.temirgaleev@tarantool.org</a>><br>Cc: tarantool-patches@dev.tarantool.org, Sergey Kaplun <<a href="mailto:skaplun@tarantool.org">skaplun@tarantool.org</a>><br>Date: Monday, June 29, 2026 4:19 PM +03:00</span><br> <div><div id=""><div class="cl-8lbx0g7vpd"><div class="js-helper_mr_css_attr js-readmsg-msg_mr_css_attr"><div id="style_17827391950442860010_mr_css_attr"><div id="style_17827391950442860010_BODY_mr_css_attr">From: Mike Pall <mike><br><br>Thanks to Sergey Kaplun.<br><br>(cherry picked from commit a2bde60819d83e6f75130ac2c93ee4b3c7615800)<br><br>This commit fixes the regression introduced by the commit<br>82ca6844234901366c043cd103f6eae345af753c ("FFI/MacOS: Fix calling<br>convention for enums."). The `isva` flag is set to 0 even for vararg<br>functions. Thus, arguments on the stack may be aligned incorrectly,<br>leading to the crash.<br><br>This patch fixes the behaviour by adjusting the flag value instead of<br>resetting it. In addition to the original test, various tests have been<br>added to cover the behaviour of the vararg FFI calls.<br><br>Sergey Kaplun:<br>* added the description and the test for the problem<br><br>Part of tarantool/tarantool#12480<br>---<br><br>Branch: <a href="https://github.com/tarantool/luajit/tree/skaplun/lj-1455-macos-arm64-vararg-regression">https://github.com/tarantool/luajit/tree/skaplun/lj-1455-macos-arm64-vararg-regression</a><br>Related issues:<br>* <a href="https://github.com/LuaJIT/LuaJIT/issues/1455">https://github.com/LuaJIT/LuaJIT/issues/1455</a><br>* <a href="https://github.com/neovim/neovim/pull/39994">https://github.com/neovim/neovim/pull/39994</a><br>* <a href="https://github.com/tarantool/tarantool/issues/12480">https://github.com/tarantool/tarantool/issues/12480</a><br><br>src/lj_ccall.c | 2 +-<br>...455-macos-arm64-vararg-regression.test.lua | 112 ++++++++++++++++++<br>2 files changed, 113 insertions(+), 1 deletion(-)<br>create mode 100644 test/tarantool-tests/lj-1455-macos-arm64-vararg-regression.test.lua<br><br>diff --git a/src/lj_ccall.c b/src/lj_ccall.c<br>index 7c3ec1e5..ed692318 100644<br>--- a/src/lj_ccall.c<br>+++ b/src/lj_ccall.c<br>@@ -1082,7 +1082,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,<br>if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */<br>MSize align = (1u << ctype_align(ccall_struct_align(cts, d))) - 1;<br>#if LJ_TARGET_ARM64 && LJ_TARGET_OSX<br>- isva = ctype_isstruct(d->info);<br>+ isva |= ctype_isstruct(d->info);<br>#endif<br>if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1))<br>align = CTSIZE_PTR-1;<br>diff --git a/test/tarantool-tests/lj-1455-macos-arm64-vararg-regression.test.lua b/test/tarantool-tests/lj-1455-macos-arm64-vararg-regression.test.lua<br>new file mode 100644<br>index 00000000..a6670cce<br>--- /dev/null<br>+++ b/test/tarantool-tests/lj-1455-macos-arm64-vararg-regression.test.lua<br>@@ -0,0 +1,112 @@<br>+local ffi = require('ffi')<br>+local tap = require('tap')<br>+<br>+-- The test file to test various FFI C vararg calls.<br>+-- luacheck: push no max_comment_line_length<br>+-- Originated from: <a href="https://github.com/neovim/neovim/blob/a5aa62e37b82214a1d4d1e0a54d193b155fb340c/test/unit/strings_spec.lua">https://github.com/neovim/neovim/blob/a5aa62e37b82214a1d4d1e0a54d193b155fb340c/test/unit/strings_spec.lua</a><br>+-- luacheck: pop<br>+-- See also: <a href="https://github.com/LuaJIT/LuaJIT/issues/1455">https://github.com/LuaJIT/LuaJIT/issues/1455</a>.<br>+<br>+local test = tap.test('lj-1455-macos-arm64-vararg-regression')<br>+<br>+test:plan(45)<br>+<br>+ffi.cdef('int sprintf(char *str, const char *format, ...);')<br>+<br>+local buf = ffi.new('char[64]')<br>+<br>+local function t(expected, fmt, ...)<br>+ local args = {...}<br>+ local ctx = string.format('sprintf(buf, "%s"', fmt)<br>+ for _, x in ipairs(args) do<br>+ ctx = ctx .. ', ' .. tostring(x)<br>+ end<br>+ ctx = ctx .. string.format(') = %s', expected)<br>+<br>+ test:test(ctx, function(subtest, ...)<br>+ subtest:plan(2)<br>+ subtest:is(ffi.C.sprintf(buf, fmt, ...), #expected,<br>+ ctx .. ' - return status')<br>+ subtest:is(ffi.string(buf), expected, ctx .. ' - result string')<br>+ end, ...)<br>+end<br>+<br>+local function i(n)<br>+ return ffi.cast('int', n)<br>+end<br>+<br>+local function l(n)<br>+ return ffi.cast('long', n)<br>+end<br>+<br>+local function ll(n)<br>+ return ffi.cast('long long', n)<br>+end<br>+<br>+local function z(n)<br>+ return ffi.cast('ptrdiff_t', n)<br>+end<br>+<br>+local function u(n)<br>+ return ffi.cast('unsigned', n)<br>+end<br>+<br>+local function ul(n)<br>+ return ffi.cast('unsigned long', n)<br>+end<br>+<br>+local function ull(n)<br>+ return ffi.cast('unsigned long long', n)<br>+end<br>+<br>+local function uz(n)<br>+ return ffi.cast('size_t', n)<br>+end<br>+<br>+t('1234567', '%d', i(1234567))<br>+t('1234567', '%ld', l(1234567))<br>+t(' 1234567', '%9ld', l(1234567))<br>+t('1234567 ', '%-9ld', l(1234567))<br>+t('deadbeef', '%x', u(0xdeadbeef))<br>+t('one two', '%s %s', 'one', 'two')<br>+t('1.234000', '%f', 1.234)<br>+t('1.234000e+00', '%e', 1.234)<br>+t('inf', '%f', 1.0 / 0.0)<br>+t('-inf', '%f', -1.0 / 0.0)<br>+t('-0.000000', '%f', tonumber('-0.0'))<br>+t('%%%', '%%%%%%')<br>+t('0x87654321', '%p', ffi.cast('char *', 0x87654321))<br>+t('0x0087654321', '%012p', ffi.cast('char *', 0x87654321))<br>+t('1234567 ', '%1$*2$ld', l(1234567), i(-9))<br>+t('1234567 ', '%1$*2$.*3$ld', l(1234567), i(-9), i(5))<br>+t('1234567 ', '%1$*3$.*2$ld', l(1234567), i(5), i(-9))<br>+t('1234567 ', '%3$*1$.*2$ld', i(-9), i(5), l(1234567))<br>+t('1234567', '%1$ld', l(1234567))<br>+t(' 1234567', '%1$*2$ld', l(1234567), i(9))<br>+t('9 12345 7654321', '%2$ld %1$d %3$lu', i(12345), l(9), ul(7654321))<br>+t('9 1234567 7654321', '%2$d %1$ld %3$lu', l(1234567), i(9), ul(7654321))<br>+t('9 1234567 7654321', '%2$d %1$lld %3$lu', ll(1234567), i(9), ul(7654321))<br>+t('9 12345 7654321', '%2$ld %1$u %3$lu', u(12345), l(9), ul(7654321))<br>+t('9 1234567 7654321', '%2$d %1$lu %3$lu', ul(1234567), i(9), ul(7654321))<br>+t('9 1234567 7654321', '%2$d %1$llu %3$lu', ull(1234567), i(9), ul(7654321))<br>+t('9 deadbeef 7654321', '%2$d %1$x %3$lu', u(0xdeadbeef), i(9), ul(7654321))<br>+t('9 c 7654321', '%2$ld %1$c %3$lu', i(('c'):byte()), l(9), ul(7654321))<br>+t('9 hi 7654321', '%2$ld %1$s %3$lu', 'hi', l(9), ul(7654321))<br>+t('9 0.000000e+00 7654321', '%2$ld %1$e %3$lu', 0.0, l(9), ul(7654321))<br>+t('two one two', '%2$s %1$s %2$s', 'one', 'two', 'three')<br>+t('three one two', '%3$s %1$s %2$s', 'one', 'two', 'three')<br>+t('1234567', '%1$d', i(1234567))<br>+t('deadbeef', '%1$x', u(0xdeadbeef))<br>+t('one two', '%1$s %2$s', 'one', 'two')<br>+t('two one', '%2$s %1$s', 'one', 'two')<br>+t('1.234000', '%1$f', 1.234)<br>+t('1.234000e+00', '%1$e', 1.234)<br>+t('inf', '%1$f', 1.0 / 0.0)<br>+t('-inf', '%1$f', -1.0 / 0.0)<br>+t('-0.000000', '%1$f', tonumber('-0.0'))<br>+t('-1234567 -7654321', '%zd %zd', z(-1234567), z(-7654321))<br>+t('-7654321 -1234567', '%2$zd %1$zd', z(-1234567), z(-7654321))<br>+t('1234567 7654321', '%zu %zu', uz(1234567), uz(7654321))<br>+t('7654321 1234567', '%2$zu %1$zu', uz(1234567), uz(7654321))<br>+<br>+test:done(true)<br>--<br>2.54.0</div></div></div></div></div></div></blockquote></div></div></BODY></HTML>