From d765a4631235a5f6754f3d84410e5528d04436d1 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 26 Feb 2026 22:29:53 +0000 Subject: [PATCH 1/2] Issue server/2342: change assert in serialization to not fire for pc if script in crashed state. Set run bit on two buld scripts. --- .gitignore | 1 + VM/src/ares.cpp | 4 ++-- build-cmd.sh | 0 init_debian_buster.sh | 0 4 files changed, 3 insertions(+), 2 deletions(-) mode change 100644 => 100755 build-cmd.sh mode change 100644 => 100755 init_debian_buster.sh diff --git a/.gitignore b/.gitignore index 2702e8e6..0825eb88 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ __pycache__ *.rej /fuzz/corpus/json/* !/fuzz/corpus/json/*.json +*.code-workspace diff --git a/VM/src/ares.cpp b/VM/src/ares.cpp index 89e66818..152fe138 100644 --- a/VM/src/ares.cpp +++ b/VM/src/ares.cpp @@ -2268,8 +2268,8 @@ p_thread(Info *info) { /* ... thread */ // PC relative to the start of the code int64_t pc_offset = ci->savedpc - lcl->l.p->code; - // the PC had better be in bounds. - eris_assert(pc_offset >= 0 && pc_offset < lcl->l.p->sizecode); + // If we have a thread that hasn't been hard-killed, the PC had better be in bounds. + eris_assert(thread->status != LUA_ERRKILL && pc_offset >= 0 && pc_offset < lcl->l.p->sizecode); int yield_point = -1; for (int j = 0; j< lcl->l.p->sizeyieldpoints; ++j) { diff --git a/build-cmd.sh b/build-cmd.sh old mode 100644 new mode 100755 diff --git a/init_debian_buster.sh b/init_debian_buster.sh old mode 100644 new mode 100755 From 941d1cc8e9c5aad13a4e1c4a21e8d45cf94a5b50 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 27 Feb 2026 19:49:40 +0000 Subject: [PATCH 2/2] Remove the assert entirely. Add range checks when deserializing against invalid bytecode. --- VM/src/ares.cpp | 5 +++-- VM/src/lvmload.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/VM/src/ares.cpp b/VM/src/ares.cpp index 152fe138..4a277686 100644 --- a/VM/src/ares.cpp +++ b/VM/src/ares.cpp @@ -1780,6 +1780,9 @@ u_proto(Info *info) { /* ... proto */ for (i=0; isizeyieldpoints; ++i) { p->yieldpoints[i] = READ_VALUE(int32_t); + if (p->yieldpoints[i] < 0 || p->yieldpoints[i] >= p->sizecode) { + eris_error(info, "malformed data: invalid yield point"); + } } // Assign bytecodeid at the end after all dangerous unpersist calls @@ -2268,8 +2271,6 @@ p_thread(Info *info) { /* ... thread */ // PC relative to the start of the code int64_t pc_offset = ci->savedpc - lcl->l.p->code; - // If we have a thread that hasn't been hard-killed, the PC had better be in bounds. - eris_assert(thread->status != LUA_ERRKILL && pc_offset >= 0 && pc_offset < lcl->l.p->sizecode); int yield_point = -1; for (int j = 0; j< lcl->l.p->sizeyieldpoints; ++j) { diff --git a/VM/src/lvmload.cpp b/VM/src/lvmload.cpp index 2038184e..d48c5c81 100644 --- a/VM/src/lvmload.cpp +++ b/VM/src/lvmload.cpp @@ -602,6 +602,19 @@ static int loadsafe( for (int j = 0; j < num_yields; ++j) { p->yieldpoints[j] = readVarInt(data, size, offset); + if (p->yieldpoints[j] < 0 || p->yieldpoints[j] >= p->sizecode) + { + char chunkbuf[LUA_IDSIZE]; + const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), chunkname, strlen(chunkname)); + lua_pushfstring( + L, + "%s: malformed bytecode: invalid yield point %d in proto %d", + chunkid, + p->yieldpoints[j], + i + ); + return 1; + } } protos[i] = p;