Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0014] CRASH detected in lj_ir_kgc due to a fault at or near 0x00007ff7f3274008 leading to SIGSEGV #1203

Closed
pwnhacker0x18 opened this issue May 2, 2024 · 2 comments

Comments

@pwnhacker0x18
Copy link

poc.txt

@Buristan
Copy link

Buristan commented May 3, 2024

The reason is the uint32_t underflow in J->irbotlim due to irbuf shifting up. This happens when the shift size is greater than J->irbotlim. Hence, irbufptr points to the middle of the buffer, and J->irbotlim has the "negative" offset.

(gdb) p szins >> 2
$2 = 16384
(gdb) p J->irbotlim
$3 = 15496
# And after the subtraction the limit overflows.
(gdb) p J->irbotlim
$4 = 4294966408

The dirty patch masks the issue, but obviously there should be a better way to fix it.

diff --git a/src/lj_ir.c b/src/lj_ir.c
index 9a51186f..f1b9db10 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -93,7 +93,7 @@ static void lj_ir_growbot(jit_State *J)
   lj_assertJ(szins != 0, "zero IR size");
   lj_assertJ(J->cur.nk == J->irbotlim || J->cur.nk-1 == J->irbotlim,
              "unexpected IR growth");
-  if (J->cur.nins + (szins >> 1) < J->irtoplim) {
+  if (J->cur.nins + (szins >> 1) < J->irtoplim && (szins >> 2) <= J->irbotlim) {
     /* More than half of the buffer is free on top: shift up by a quarter. */
     MSize ofs = szins >> 2;
     memmove(baseir + ofs, baseir, (J->cur.nins - J->irbotlim)*sizeof(IRIns));

MikePall pushed a commit that referenced this issue May 25, 2024
@MikePall
Copy link
Member

The IR should never grow to that point, since there are limit checks at strategic points. However compiling string.format may lead to an unlimited expansion of the IR.

I've added a (reasonable) limit. Thanks!

Simplified testcase:

local fmt = ("%"):rep(50000)
for i=1,100 do s = fmt:format() end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants