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 16EB16EFDE6; Sat, 18 Nov 2023 02:42:24 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 16EB16EFDE6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1700264544; bh=uU5P/nhMMlnF9RU++uddM4raFP0BB0giqBPGaLwUqC4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=F86LzC9ClZrjMKMHioGK37C9CXmn70+Ck2vpZCxaRxSDHcHH26rTF+97kFecmDe9A 3eKbvpElkz9X39L0troPajWR59sDODzbQ4fqnDpowgQgL3mLAKIrNI4wqAha6BtT4C ZYmXzwTXuJn7buBtq7pMh7SmhUNbKiHcZDxNrL2A= Received: from mail-lj1-f181.google.com (mail-lj1-f181.google.com [209.85.208.181]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 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 D9AE66EFDE7 for ; Sat, 18 Nov 2023 02:41:27 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org D9AE66EFDE7 Received: by mail-lj1-f181.google.com with SMTP id 38308e7fff4ca-2c509f2c46cso35674861fa.1 for ; Fri, 17 Nov 2023 15:41:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700264487; x=1700869287; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UQwSy7ar5mVnoJxiwqRq0nsyJ3dDt1gveZH+cQ/wv3A=; b=MfjAVxVw7Ao2+3dtK/3njkF/IamfC0KfTqVLW1blN2BxjyhklhIRvDa6vo3rA7DkrK o689m8LwqeVoUjD1kzoTj5iIlKZDWgyi+EfGSFj0aHtCuPhmnUjMUm4uDBcdcF/1uQ/L aPwCdUsx+C/9kKpdoScE8ru+pwlbGFWGNAXNWKSTwBKG4W2T7Xkn/YQ5w8tCsx3XaaJ1 saWNQLgD/PVg0O7UmSlvnc30CUBVRROIRb1xqyciBPjLxf9q2bLBFYNPGsOh81X5EgGE Z4IkrDr7Fk4bZ/RxO1MWi6oPn1ZJPNN4laVCbzvakjmB1Yg9ajvJ1ZjRMxCeA8lTAWPK UwmQ== X-Gm-Message-State: AOJu0YxoSx+Egj3VDdXoqng3CoMOl4/QKkjrDIQBn50XLaIb0K8n3TZp fvmG+5DSlB+U5BMjGJQubZF0Ra5ZaCael43O X-Google-Smtp-Source: AGHT+IESx0NtRHI9o/A3lTSqhClVkFP7FZytmxYVMU0mbkyebVfcYrf4FzViQpS7C52+MMM2TBF+7A== X-Received: by 2002:a2e:8e38:0:b0:2bf:7fad:229b with SMTP id r24-20020a2e8e38000000b002bf7fad229bmr679421ljk.37.1700264486802; Fri, 17 Nov 2023 15:41:26 -0800 (PST) Received: from localhost.localdomain (95-24-0-215.broadband.corbina.ru. [95.24.0.215]) by smtp.gmail.com with ESMTPSA id w14-20020a2e9bce000000b002c83b0bd971sm360587ljj.2.2023.11.17.15.41.26 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Fri, 17 Nov 2023 15:41:26 -0800 (PST) To: tarantool-patches@dev.tarantool.org, sergeyb@tarantool.org, skaplun@tarantool.org, m.kokryashkin@tarantool.org Date: Sat, 18 Nov 2023 02:41:15 +0300 Message-Id: <20231117234116.60037-3-max.kokryashkin@gmail.com> X-Mailer: git-send-email 2.39.3 (Apple Git-145) In-Reply-To: <20231117234116.60037-1-max.kokryashkin@gmail.com> References: <20231117234116.60037-1-max.kokryashkin@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH luajit 2/3] Cleanup stack overflow handling. 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: Maksim Kokryashkin via Tarantool-patches Reply-To: Maksim Kokryashkin Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall Reported by Peter Cawley. (cherry-picked from commit d2f6c55b05c716e5dbb479b7e684abaee7cf6e12) After the previous patch, it is possible to trigger the `stack overflow` error prematurely. Consider the following situation: there are already 33000 slots allocated on a Lua stack, and then there are 30 additional slots needed. In this case, the actual allocated amount would be twice the already allocated size, shrunk to the `LJ_STACK_MAXEX` size, which would lead to the stack overflow error, despite the fact there is plenty of unused space. This patch completely reworks the logic of error handling during stack growth to address the issue. Maxim Kokryashkin: * added the description and the test for the problem Part of tarantool/tarantool#9145 --- src/lj_state.c | 15 +++++-- .../lj-962-premature-stack-overflow.test.c | 41 +++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/tarantool-c-tests/lj-962-premature-stack-overflow.test.c diff --git a/src/lj_state.c b/src/lj_state.c index 76153bad..d8a5134c 100644 --- a/src/lj_state.c +++ b/src/lj_state.c @@ -121,8 +121,17 @@ void lj_state_shrinkstack(lua_State *L, MSize used) void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need) { MSize n; - if (L->stacksize > LJ_STACK_MAXEX) /* Overflow while handling overflow? */ - lj_err_throw(L, LUA_ERRERR); + if (L->stacksize >= LJ_STACK_MAXEX) { + /* 4. Throw 'error in error handling' when we are _over_ the limit. */ + if (L->stacksize > LJ_STACK_MAXEX) + lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */ + /* 1. We are _at_ the limit after the last growth. */ + if (!L->status) { /* 2. Throw 'stack overflow'. */ + L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */ + lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */ + } + /* 3. Add space (over the limit) for pushed message and error handler. */ + } n = L->stacksize + need; if (n > LJ_STACK_MAX) { n += 2*LUA_MINSTACK; @@ -132,8 +141,6 @@ void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need) n = LJ_STACK_MAX; } resizestack(L, n); - if (L->stacksize >= LJ_STACK_MAXEX) - lj_err_msg(L, LJ_ERR_STKOV); } void LJ_FASTCALL lj_state_growstack1(lua_State *L) diff --git a/test/tarantool-c-tests/lj-962-premature-stack-overflow.test.c b/test/tarantool-c-tests/lj-962-premature-stack-overflow.test.c new file mode 100644 index 00000000..0873636a --- /dev/null +++ b/test/tarantool-c-tests/lj-962-premature-stack-overflow.test.c @@ -0,0 +1,41 @@ +#include "lua.h" +#include "lauxlib.h" + +#include "test.h" +#include "utils.h" + +#include "lj_obj.h" +#include "luaconf.h" + +static int cur_slots = -1; + +static int fill_stack(lua_State *L) +{ + cur_slots = L->base - tvref(L->stack); + + while(lua_gettop(L) < LUAI_MAXSTACK) { + cur_slots += 1; + lua_pushinteger(L, 42); + } + + return 1; +} + +static int premature_stackoverflow(void *test_state) +{ + lua_State *L = test_state; + lua_cpcall(L, fill_stack, NULL); + assert_true(cur_slots == LUAI_MAXSTACK - 1); + return TEST_EXIT_SUCCESS; +} + +int main(void) +{ + lua_State *L = utils_lua_init(); + const struct test_unit tgroup[] = { + test_unit_def(premature_stackoverflow), + }; + const int test_result = test_run_group(tgroup, L); + utils_lua_close(L); + return test_result; +} -- 2.39.3 (Apple Git-145)