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 1DF546EC44; Wed, 11 Nov 2026 16:38:47 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 1DF546EC44 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1794404327; bh=MoF5F70lhXhuadtOW0S+sJTmsSTCDWVKKPVqWha3N/E=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=oHAfBLfy0mAiiP9N6W9B3tzfSZtjlCMudbeqnghIPQ40ADPSHY2ywQwmEepZ4Iffe Wo3/TvCzTXDIYU9eqI/L3oBOFFQWzYjZpvxgF/axuN2p1H4Qbmuexn9UnyodruvOfB H/Pm8uEKtTKx1Kryngt2I0EQF6pTy7SbZJMZPcj8= Received: from send57.i.mail.ru (send57.i.mail.ru [89.221.237.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id C4A906EC44 for ; Wed, 11 Nov 2026 16:38:45 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C4A906EC44 Received: by exim-smtp-bccb94844-2lg6s with esmtpa (envelope-from ) id 1xR8XE-000000001I1-2EvR; Wed, 11 Nov 2026 16:38:45 +0300 To: Sergey Bronnikov , Evgeniy Temirgaleev Date: Wed, 11 Nov 2026 16:38:05 +0300 Message-ID: <20261111133805.1497870-1-skaplun@tarantool.org> X-Mailer: git-send-email 2.56.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD960A32E02787845123C321558CF4C0362312ECB581DC96AC3182A05F53808504004E62CFC467A26B93DE06ABAFEAF67050D0F6840161E73AFD7C2894732E7AF56F14F8599D8FED5CC X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE71BDE6A359BD5B800EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AC83A81C8FD4AD23D82A6BABE6F325AC2E85FA5F3EDFCBAA7353EFBB553375661F398E59D6539FAA3DC36AB40645F3346E932A78A07DF1002C4EC30E22560C6E389733CBF5DBD5E9D5E8D9A59859A8B6AEEA5BB16A939343CC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB8090A508E0FED6299176DF2183F8FC7C0A825F8AE102D15AACD04E86FAF290E2DB606B96278B59C421DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B60A9A04DE7321024275ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: 0D63561A33F958A5405A99DD7DCBCA1F5002B1117B3ED6966C645DD8EAE4493EBFF4097FFC9E796F823CB91A9FED034534781492E4B8EEAD81B3E0F64AD3EF57C79554A2A72441328621D336A7BC284946AD531847A6065A535571D14F44ED41 X-C8649E89: 1C3962B70DF3F0AD73CAD6646DEDE1918E10F71CB4DF9F9677DD89D51EBB774225B6776AC983F447FC0B9F89525902EE6F57B2FD27647F25E66C117BDB76D6598006CEB31917ABFCE1497A1687315369881DDD395B28183C0D8781ABD843F96065D66F1EFC923D58B8341EE9D5BE9A0AFD30B7D7CE86BEC6DC2C1240C481DC974BD898BC429C7704C7CEAA0681F5848F4C41F94D744909CECFA6C6B0C050A61A8CAF69B82BA93681CD72808BE417F3B9E0E7457915DAA85F X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXOcIETfglQORZ0zpDET4Zrk3igikrdHlWN/WkZFYcbu4m5/lFOSIJYM= X-Mailru-Sender: 520A125C2F17F0B17094CDC02B85F11BE7876F9F07A83FCD3DE06ABAFEAF67050D0F6840161E73AFB7CBEF92542CD7C88B0A2698F12F5C9EC77752E0C033A69E86920BD37369036789A8C6A0E60D2BB63A5DB60FBEB33A8A0DA7A0AF5A3A8387 X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit] Clarify that lj_buf_shrink() does not keep any buffer data. 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: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall https://www.freelists.org/post/luajit/lj-buf-shrink-may-truncate-the-data-and-sbw-point-over-the-end-of-the-buffer,1 Thanks to Junlong li. (cherry picked from commit 444c8ff19a39248307a7037354d6d259cc0e5efc) When `lj_cf_string_format()` formats any object to the string via `%s` it casts this object to a string implicitly on the first pass of parsing the regexp. If the `__tostring` metamethod of the object invokes the atomic step of the GC, GC shrinks the `tmpbuf` is used for string formatting. In case when the result string occupies more than half of the buffer, the writes in the second pass miss the buffer and may lead to the heap-buffer-overflow, an invalid result string, or the core dump. This patch resets the current pointer position in the buffer in the `lj_buf_shrink()` to avoid incorrect buffer writes. Sergey Kaplun: * added the description and the test for the problem Resolves tarantool/tarantool#4171 Part of tarantool/tarantool#13442 --- Branch: https://github.com/tarantool/luajit/tree/skaplun/gh-4171-lj-cf-string-format-atomic Related issues: * https://github.com/tarantool/tarantool/issues/4171 * https://github.com/tarantool/tarantool/issues/13442 src/lj_buf.c | 3 +- ...h-4171-lj-cf-string-format-atomic.test.lua | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test/tarantool-tests/gh-4171-lj-cf-string-format-atomic.test.lua diff --git a/src/lj_buf.c b/src/lj_buf.c index 923f4276..bcfc4c93 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c @@ -52,10 +52,9 @@ void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb) char *b = sbufB(sb); MSize osz = (MSize)(sbufE(sb) - b); if (osz > 2*LJ_MIN_SBUF) { - MSize n = (MSize)(sbufP(sb) - b); b = lj_mem_realloc(L, b, osz, (osz >> 1)); setmref(sb->b, b); - setmref(sb->p, b + n); + setmref(sb->p, b); /* Not supposed to keep data across shrinks. */ setmref(sb->e, b + (osz >> 1)); } } diff --git a/test/tarantool-tests/gh-4171-lj-cf-string-format-atomic.test.lua b/test/tarantool-tests/gh-4171-lj-cf-string-format-atomic.test.lua new file mode 100644 index 00000000..c601ce08 --- /dev/null +++ b/test/tarantool-tests/gh-4171-lj-cf-string-format-atomic.test.lua @@ -0,0 +1,30 @@ +local tap = require('tap') + +-- The test file demonstrates `string.format()` +-- heap-buffer-overflow under ASAN if the atomic phase of the GC +-- is entered during the first pass of formatting with implicit +-- conversion of the argument to a string via %s. +-- See also: https://github.com/tarantool/tarantool/issues/4171. +local test = tap.test('gh-4171-lj-cf-string-format-atomic') + +test:plan(1) + +local obj = setmetatable({}, { + __tostring = function() + -- Shrinks `tmpbuf`: 256 -> 128 (but length of string is 200). + collectgarbage() + return 'x' + end +}) + +local prefix = string.rep('a', 200) + +-- %s triggers a full GC cycle, including `tmpbuf` shrinking in +-- the atomic phase. '_suffix' was written outside the buffer +-- before the patch. +local res = string.format(prefix .. '%s_suffix', obj) + +-- Under ASAN this leads to heap-buffer-overflow. +test:is(res, prefix .. 'x_suffix', 'correct string format result') + +test:done(true) -- 2.56.0