Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/core/ldo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ void lua_State::hookCall(CallInfo *ci_arg) {
// Convert to private lua_State method
void lua_State::retHook(CallInfo *ci_arg, int nres) {
if (getHookMask() & LUA_MASKRET) { /* is return hook on? */
lua_assert(getTop().p >= getStack().p + nres); /* ensure nres is in bounds */
StkId firstres = getTop().p - nres; /* index of first result */
int delta = 0; /* correction for vararg functions */
int ftransfer;
Expand Down Expand Up @@ -426,6 +427,7 @@ unsigned lua_State::tryFuncTM(StkId func, unsigned status_val) {
tm = luaT_gettmbyobj(this, s2v(func), TMS::TM_CALL);
if (l_unlikely(ttisnil(tm))) /* no metamethod? */
luaG_callerror(this, s2v(func));
lua_assert(func >= getStack().p && getTop().p > func); /* ensure valid bounds */
for (p = getTop().p; p > func; p--) /* open space for metamethod */
*s2v(p) = *s2v(p-1); /* shift stack - use operator= */
getStackSubsystem().push(); /* stack space pre-allocated by the caller */
Expand All @@ -440,10 +442,12 @@ unsigned lua_State::tryFuncTM(StkId func, unsigned status_val) {
// Convert to private lua_State method
void lua_State::genMoveResults(StkId res, int nres,
int wanted) {
lua_assert(nres >= 0 && getTop().p >= getStack().p + nres); /* ensure nres valid */
StkId firstresult = getTop().p - nres; /* index of first result */
int i;
if (nres > wanted) /* extra results? */
nres = wanted; /* don't need them */
lua_assert(firstresult >= getStack().p && res >= getStack().p); /* ensure valid pointers */
for (i = 0; i < nres; i++) /* move all results to correct place */
*s2v(res + i) = *s2v(firstresult + i); /* use operator= */
for (; i < wanted; i++) /* complete wanted number of results */
Expand Down
5 changes: 4 additions & 1 deletion src/libraries/lstrlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,7 @@ static int str_pack (lua_State *L) {
case Kint: { /* signed integers */
lua_Integer n = luaL_checkinteger(L, arg);
if (size < SZINT) { /* need overflow check? */
lua_assert(size > 0); /* ensure size > 0 to avoid negative shift */
lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
}
Expand All @@ -1639,9 +1640,11 @@ static int str_pack (lua_State *L) {
}
case Kuint: { /* unsigned integers */
lua_Integer n = luaL_checkinteger(L, arg);
if (size < SZINT) /* need overflow check? */
if (size < SZINT) { /* need overflow check? */
lua_assert(size > 0); /* ensure size > 0 to avoid negative shift */
luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
arg, "unsigned overflow");
}
packint(&b, (lua_Unsigned)n, h.islittle, cast_uint(size), 0);
break;
}
Expand Down
25 changes: 25 additions & 0 deletions src/memory/llimits.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,31 @@ inline constexpr bool ispow2(T x) noexcept {
}


/*
** Safe multiplication helpers - check for overflow before multiplication
** These functions return true if the multiplication would overflow
*/

/* Check if multiplication a * b would overflow size_t */
inline constexpr bool wouldMultiplyOverflow(size_t a, size_t b) noexcept {
if (a == 0 || b == 0)
return false;
return a > MAX_SIZET / b;
}

/* Check if multiplication a * b would overflow for a specific type size */
inline constexpr bool wouldSizeMultiplyOverflow(size_t count, size_t elemSize) noexcept {
return wouldMultiplyOverflow(count, elemSize);
}

/* Safe multiplication - returns 0 on overflow (for allocation failure path) */
inline constexpr size_t safeMul(size_t a, size_t b) noexcept {
if (wouldMultiplyOverflow(a, b))
return 0;
return a * b;
}


/* number of chars of a literal string without the ending \0 */
template<size_t N>
inline constexpr size_t LL(const char (&)[N]) noexcept {
Expand Down
10 changes: 8 additions & 2 deletions src/objects/lobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,14 @@ class GCObject {
bool isMarked() const noexcept { return marked != 0; }

// Marked field bit manipulation methods (const - marked is mutable)
void setMarkedBit(int bit) const noexcept { marked |= cast_byte(1 << bit); }
void clearMarkedBit(int bit) const noexcept { marked &= cast_byte(~(1 << bit)); }
void setMarkedBit(int bit) const noexcept {
lua_assert(bit >= 0 && bit < 8); /* lu_byte is 8 bits */
marked |= cast_byte(1 << bit);
}
void clearMarkedBit(int bit) const noexcept {
lua_assert(bit >= 0 && bit < 8); /* lu_byte is 8 bits */
marked &= cast_byte(~(1 << bit));
}
void clearMarkedBits(int mask) const noexcept { marked &= cast_byte(~mask); }

// Marked field bit manipulation helpers (for backward compatibility)
Expand Down
10 changes: 8 additions & 2 deletions src/objects/ltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,8 +674,14 @@ static void numusehash (const Table *t, Counters *ct) {
static size_t concretesize (unsigned int size) {
if (size == 0)
return 0;
else /* space for the two arrays plus an unsigned in between */
return size * (sizeof(Value) + 1) + sizeof(unsigned);
else {
/* space for the two arrays plus an unsigned in between */
size_t elemSize = sizeof(Value) + 1;
/* Check for overflow in multiplication */
if (wouldSizeMultiplyOverflow(size, elemSize))
return 0; /* Signal overflow to caller */
return size * elemSize + sizeof(unsigned);
}
}


Expand Down
3 changes: 3 additions & 0 deletions src/vm/lvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ void luaV_finishOp (lua_State *L) {
case OP_LTI: case OP_LEI:
case OP_GTI: case OP_GEI:
case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */
lua_assert(L->getTop().p > L->getStack().p); /* ensure stack not empty */
int res = !l_isfalse(s2v(L->getTop().p - 1));
L->getStackSubsystem().pop();
lua_assert(InstructionView(*ci->getSavedPC()).opcode() == OP_JMP);
Expand All @@ -184,6 +185,8 @@ void luaV_finishOp (lua_State *L) {
case OP_CONCAT: {
StkId top = L->getTop().p - 1; /* top when 'luaT_tryconcatTM' was called */
int a = InstructionView(inst).a(); /* first element to concatenate */
lua_assert(top >= base + a + 1); /* ensure valid range for subtraction */
lua_assert(top >= L->getStack().p + 2); /* ensure top-2 is valid */
int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */
*s2v(top - 2) = *s2v(top); /* put TM result in proper position (operator=) */
L->getStackSubsystem().setTopPtr(top - 1); /* top is one after last element (at top-2) */
Expand Down
11 changes: 9 additions & 2 deletions src/vm/lvm_loops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,15 @@ int lua_State::forPrep(StkId ra) {
}
else { /* step < 0; descending loop */
count = l_castS2U(init) - l_castS2U(limit);
/* 'step+1' avoids negating 'mininteger' */
count /= l_castS2U(-(step + 1)) + 1u;
/* Handle LUA_MININTEGER edge case explicitly */
if (l_unlikely(step == LUA_MININTEGER)) {
/* For step == LUA_MININTEGER, count should be divided by max value */
count /= l_castS2U(LUA_MAXINTEGER) + 1u;
}
else {
/* 'step+1' avoids negating 'mininteger' in normal case */
count /= l_castS2U(-(step + 1)) + 1u;
}
}
/* use 'chgivalue' for places that for sure had integers */
chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */
Expand Down
Loading