diff --git a/src/compiler/lcode.cpp b/src/compiler/lcode.cpp index 5b1bf49c..5e267e53 100644 --- a/src/compiler/lcode.cpp +++ b/src/compiler/lcode.cpp @@ -800,7 +800,8 @@ int FuncState::constfolding(int op, expdesc *e1, const expdesc *e2) { TValue v1, v2, res; if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) return 0; /* non-numeric operands or not safe to fold */ - luaO_rawarith(getLexState()->getLuaState(), op, &v1, &v2, &res); /* does operation */ + if (!luaO_rawarith(getLexState()->getLuaState(), op, &v1, &v2, &res)) + return 0; /* operation failed */ if (ttisinteger(&res)) { e1->setKind(VKINT); e1->setIntValue(ivalue(&res)); diff --git a/src/core/lstack.cpp b/src/core/lstack.cpp index 74397339..a37b432e 100644 --- a/src/core/lstack.cpp +++ b/src/core/lstack.cpp @@ -303,8 +303,25 @@ int LuaStack::grow(lua_State* L, int n, int raiseerror) { return 0; /* if not 'raiseerror', just signal it */ } else if (n < MAXSTACK) { /* avoids arithmetic overflows */ - int newsize = size + (size >> 1); /* tentative new size (size * 1.5) */ - int needed = cast_int(top.p - stack.p) + n; + int newsize; + /* Check for overflow in size * 1.5 calculation */ + if (size > INT_MAX / 3 * 2) { + /* size + (size >> 1) could overflow, use MAXSTACK */ + newsize = MAXSTACK; + } else { + newsize = size + (size >> 1); /* tentative new size (size * 1.5) */ + } + + /* Safe calculation of needed space */ + ptrdiff_t stack_used = top.p - stack.p; + lua_assert(stack_used >= 0 && stack_used <= INT_MAX); + int needed; + if (stack_used > INT_MAX - n) { + /* needed calculation would overflow, use MAXSTACK */ + needed = MAXSTACK; + } else { + needed = cast_int(stack_used) + n; + } if (newsize > MAXSTACK) /* cannot cross the limit */ newsize = MAXSTACK; diff --git a/src/objects/lobject.cpp b/src/objects/lobject.cpp index a6c7caba..a5c12678 100644 --- a/src/objects/lobject.cpp +++ b/src/objects/lobject.cpp @@ -34,8 +34,10 @@ /* ** Computes ceil(log2(x)), which is the smallest integer n such that ** x <= (1 << n). +** Precondition: x > 0 (ceil(log2(0)) is undefined) */ lu_byte luaO_ceillog2 (unsigned int x) { + lua_assert(x > 0); /* ceil(log2(0)) is undefined */ static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, diff --git a/src/objects/lobject.h b/src/objects/lobject.h index e18b1d71..b970025a 100644 --- a/src/objects/lobject.h +++ b/src/objects/lobject.h @@ -1795,18 +1795,18 @@ inline constexpr int UTF8BUFFSZ = 8; if (msg == nullptr) (L)->doThrow(LUA_ERRMEM); /* only after 'va_end' */ } -LUAI_FUNC int luaO_utf8esc (char *buff, l_uint32 x); -LUAI_FUNC lu_byte luaO_ceillog2 (unsigned int x); -LUAI_FUNC lu_byte luaO_codeparam (unsigned int p); -LUAI_FUNC l_mem luaO_applyparam (lu_byte p, l_mem x); +[[nodiscard]] LUAI_FUNC int luaO_utf8esc (char *buff, l_uint32 x); +[[nodiscard]] LUAI_FUNC lu_byte luaO_ceillog2 (unsigned int x); +[[nodiscard]] LUAI_FUNC lu_byte luaO_codeparam (unsigned int p); +[[nodiscard]] LUAI_FUNC l_mem luaO_applyparam (lu_byte p, l_mem x); -LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, +[[nodiscard]] LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res); LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, StkId res); -LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); -LUAI_FUNC unsigned luaO_tostringbuff (const TValue *obj, char *buff); -LUAI_FUNC lu_byte luaO_hexavalue (int c); +[[nodiscard]] LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); +[[nodiscard]] LUAI_FUNC unsigned luaO_tostringbuff (const TValue *obj, char *buff); +[[nodiscard]] LUAI_FUNC lu_byte luaO_hexavalue (int c); LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); @@ -1844,11 +1844,11 @@ LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); /* Forward declarations for comparison helpers (defined in lvm.cpp and lstring.h) */ /* These handle mixed int/float comparisons correctly */ -LUAI_FUNC int LTintfloat (lua_Integer i, lua_Number f); -LUAI_FUNC int LEintfloat (lua_Integer i, lua_Number f); -LUAI_FUNC int LTfloatint (lua_Number f, lua_Integer i); -LUAI_FUNC int LEfloatint (lua_Number f, lua_Integer i); -LUAI_FUNC int l_strcmp (const TString* ts1, const TString* ts2); +[[nodiscard]] LUAI_FUNC int LTintfloat (lua_Integer i, lua_Number f); +[[nodiscard]] LUAI_FUNC int LEintfloat (lua_Integer i, lua_Number f); +[[nodiscard]] LUAI_FUNC int LTfloatint (lua_Number f, lua_Integer i); +[[nodiscard]] LUAI_FUNC int LEfloatint (lua_Number f, lua_Integer i); +[[nodiscard]] LUAI_FUNC int l_strcmp (const TString* ts1, const TString* ts2); /* luaS_eqstr declared in lstring.h */ /* String comparison helpers (defined in lstring.h) */ diff --git a/src/objects/ltable.cpp b/src/objects/ltable.cpp index b2534404..60cb8ccb 100644 --- a/src/objects/ltable.cpp +++ b/src/objects/ltable.cpp @@ -412,6 +412,8 @@ static int equalkey (const TValue *k1, const Node *n2, int deadok) { */ static TValue *getgeneric (Table *t, const TValue *key, int deadok) { Node *n = mainpositionTV(t, key); + const Node *base = gnode(t, 0); + const Node *limit = base + t->nodeSize(); for (;;) { /* check whether 'key' is somewhere in the chain */ if (equalkey(key, n, deadok)) return gval(n); /* that's it */ @@ -420,6 +422,7 @@ static TValue *getgeneric (Table *t, const TValue *key, int deadok) { if (nx == 0) return &absentkey; /* not found */ n += nx; + lua_assert(n >= base && n < limit); /* ensure we stay in bounds */ } } } @@ -477,7 +480,12 @@ static unsigned findindex (lua_State *L, Table *t, TValue *key, const TValue *n = getgeneric(t, key, 1); if (l_unlikely(isabstkey(n))) luaG_runerror(L, "invalid key to 'next'"); /* key not found */ - i = cast_uint(reinterpret_cast(n) - gnode(t, 0)); /* key index in hash table */ + /* Calculate index in hash table with bounds checking */ + const Node* node_ptr = reinterpret_cast(n); + const Node* base = gnode(t, 0); + ptrdiff_t diff = node_ptr - base; + lua_assert(diff >= 0 && static_cast(diff) < t->nodeSize()); + i = cast_uint(diff); /* hash elements are numbered after array ones */ return (i + 1) + asize; } diff --git a/src/vm/lvm.h b/src/vm/lvm.h index 65ba4398..9dde0ff8 100644 --- a/src/vm/lvm.h +++ b/src/vm/lvm.h @@ -151,7 +151,7 @@ inline bool tointegerns(const TValue* o, lua_Integer* i) noexcept { #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) /* Forward declaration for luaV_equalobj (defined in lvm.cpp) */ -LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); +[[nodiscard]] LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); inline int luaV_rawequalobj(const TValue* t1, const TValue* t2) noexcept { return *t1 == *t2; /* Use operator== for raw equality */ @@ -224,7 +224,7 @@ inline void luaV_finishfastset(lua_State* L, const TValue* t, const TValue* v) n ** Shift right is the same as shift left with a negative 'y' */ /* Forward declaration for luaV_shiftl (full declaration below) */ -LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); +[[nodiscard]] LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); inline lua_Integer luaV_shiftr(lua_Integer x, lua_Integer y) noexcept { return luaV_shiftl(x, intop(-, 0, y)); @@ -232,8 +232,8 @@ inline lua_Integer luaV_shiftr(lua_Integer x, lua_Integer y) noexcept { -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +[[nodiscard]] LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +[[nodiscard]] LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); #ifndef luaV_flttointeger_declared #define luaV_flttointeger_declared LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); @@ -245,9 +245,9 @@ LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y); +[[nodiscard]] LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y); +[[nodiscard]] LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +[[nodiscard]] LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y); LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); #endif diff --git a/src/vm/lvm_comparison.cpp b/src/vm/lvm_comparison.cpp index ae2346d1..4dc7921d 100644 --- a/src/vm/lvm_comparison.cpp +++ b/src/vm/lvm_comparison.cpp @@ -31,7 +31,7 @@ ** of the strings. Note that segments can compare equal but still ** have different lengths. */ -int l_strcmp (const TString *ts1, const TString *ts2) { +[[nodiscard]] int l_strcmp (const TString *ts1, const TString *ts2) { size_t rl1; /* real length */ const char *s1 = getlstr(ts1, rl1); size_t rl2; @@ -75,7 +75,7 @@ int l_strcmp (const TString *ts1, const TString *ts2) { ** potentially giving incorrect results. Instead, we compute ceil(f) as an ** integer and compare in the integer domain where no precision is lost. */ -int LTintfloat (lua_Integer i, lua_Number f) { +[[nodiscard]] int LTintfloat (lua_Integer i, lua_Number f) { if (l_intfitsf(i)) return luai_numlt(cast_num(i), f); /* compare them as floats */ else { /* i < f <=> i < ceil(f) */ @@ -92,7 +92,7 @@ int LTintfloat (lua_Integer i, lua_Number f) { ** Check whether integer 'i' is less than or equal to float 'f'. ** See comments on previous function. */ -int LEintfloat (lua_Integer i, lua_Number f) { +[[nodiscard]] int LEintfloat (lua_Integer i, lua_Number f) { if (l_intfitsf(i)) return luai_numle(cast_num(i), f); /* compare them as floats */ else { /* i <= f <=> i <= floor(f) */ @@ -109,7 +109,7 @@ int LEintfloat (lua_Integer i, lua_Number f) { ** Check whether float 'f' is less than integer 'i'. ** See comments on previous function. */ -int LTfloatint (lua_Number f, lua_Integer i) { +[[nodiscard]] int LTfloatint (lua_Number f, lua_Integer i) { if (l_intfitsf(i)) return luai_numlt(f, cast_num(i)); /* compare them as floats */ else { /* f < i <=> floor(f) < i */ @@ -126,7 +126,7 @@ int LTfloatint (lua_Number f, lua_Integer i) { ** Check whether float 'f' is less than or equal to integer 'i'. ** See comments on previous function. */ -int LEfloatint (lua_Number f, lua_Integer i) { +[[nodiscard]] int LEfloatint (lua_Number f, lua_Integer i) { if (l_intfitsf(i)) return luai_numle(f, cast_num(i)); /* compare them as floats */ else { /* f <= i <=> ceil(f) <= i */