mirror of
https://github.com/lua/lua
synced 2024-11-22 04:41:23 +03:00
Maximum stack size may not fit in unsigned short
Therefore, fields ftransfer/ntransfer in lua_Debug must have type 'int'. (Maximum stack size must fit in an 'int'.) Also, this commit adds check that maximum stack size respects size_t for size in bytes.
This commit is contained in:
parent
6b45ccf4ed
commit
cd4de92762
43
ldo.c
43
ldo.c
@ -171,6 +171,24 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
|||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* some stack space for error handling */
|
||||||
|
#define STACKERRSPACE 200
|
||||||
|
|
||||||
|
|
||||||
|
/* maximum stack size that respects size_t */
|
||||||
|
#define MAXSTACK_BYSIZET ((MAX_SIZET / sizeof(StackValue)) - STACKERRSPACE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Minimum between LUAI_MAXSTACK and MAXSTACK_BYSIZET
|
||||||
|
** (Maximum size for the stack must respect size_t.)
|
||||||
|
*/
|
||||||
|
#define MAXSTACK cast_int(LUAI_MAXSTACK < MAXSTACK_BYSIZET \
|
||||||
|
? LUAI_MAXSTACK : MAXSTACK_BYSIZET)
|
||||||
|
|
||||||
|
|
||||||
|
/* stack size with extra space for error handling */
|
||||||
|
#define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change all pointers to the stack into offsets.
|
** Change all pointers to the stack into offsets.
|
||||||
@ -208,9 +226,6 @@ static void correctstack (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* some space for error handling */
|
|
||||||
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Reallocate the stack to a new size, correcting all pointers into it.
|
** Reallocate the stack to a new size, correcting all pointers into it.
|
||||||
** In ISO C, any pointer use after the pointer has been deallocated is
|
** In ISO C, any pointer use after the pointer has been deallocated is
|
||||||
@ -227,7 +242,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
|||||||
int i;
|
int i;
|
||||||
StkId newstack;
|
StkId newstack;
|
||||||
int oldgcstop = G(L)->gcstopem;
|
int oldgcstop = G(L)->gcstopem;
|
||||||
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
lua_assert(newsize <= MAXSTACK || newsize == ERRORSTACKSIZE);
|
||||||
relstack(L); /* change pointers to offsets */
|
relstack(L); /* change pointers to offsets */
|
||||||
G(L)->gcstopem = 1; /* stop emergency collection */
|
G(L)->gcstopem = 1; /* stop emergency collection */
|
||||||
newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK,
|
newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK,
|
||||||
@ -254,7 +269,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
|||||||
*/
|
*/
|
||||||
int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
||||||
int size = stacksize(L);
|
int size = stacksize(L);
|
||||||
if (l_unlikely(size > LUAI_MAXSTACK)) {
|
if (l_unlikely(size > MAXSTACK)) {
|
||||||
/* if stack is larger than maximum, thread is already using the
|
/* if stack is larger than maximum, thread is already using the
|
||||||
extra space reserved for errors, that is, thread is handling
|
extra space reserved for errors, that is, thread is handling
|
||||||
a stack error; cannot grow further than that. */
|
a stack error; cannot grow further than that. */
|
||||||
@ -263,14 +278,14 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
|||||||
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
|
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
|
||||||
return 0; /* if not 'raiseerror', just signal it */
|
return 0; /* if not 'raiseerror', just signal it */
|
||||||
}
|
}
|
||||||
else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */
|
else if (n < MAXSTACK) { /* avoids arithmetic overflows */
|
||||||
int newsize = 2 * size; /* tentative new size */
|
int newsize = 2 * size; /* tentative new size */
|
||||||
int needed = cast_int(L->top.p - L->stack.p) + n;
|
int needed = cast_int(L->top.p - L->stack.p) + n;
|
||||||
if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */
|
if (newsize > MAXSTACK) /* cannot cross the limit */
|
||||||
newsize = LUAI_MAXSTACK;
|
newsize = MAXSTACK;
|
||||||
if (newsize < needed) /* but must respect what was asked for */
|
if (newsize < needed) /* but must respect what was asked for */
|
||||||
newsize = needed;
|
newsize = needed;
|
||||||
if (l_likely(newsize <= LUAI_MAXSTACK))
|
if (l_likely(newsize <= MAXSTACK))
|
||||||
return luaD_reallocstack(L, newsize, raiseerror);
|
return luaD_reallocstack(L, newsize, raiseerror);
|
||||||
}
|
}
|
||||||
/* else stack overflow */
|
/* else stack overflow */
|
||||||
@ -306,17 +321,17 @@ static int stackinuse (lua_State *L) {
|
|||||||
** to twice the current use. (So, the final stack size is at most 2/3 the
|
** to twice the current use. (So, the final stack size is at most 2/3 the
|
||||||
** previous size, and half of its entries are empty.)
|
** previous size, and half of its entries are empty.)
|
||||||
** As a particular case, if stack was handling a stack overflow and now
|
** As a particular case, if stack was handling a stack overflow and now
|
||||||
** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than
|
** it is not, 'max' (limited by MAXSTACK) will be smaller than
|
||||||
** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack
|
** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack
|
||||||
** will be reduced to a "regular" size.
|
** will be reduced to a "regular" size.
|
||||||
*/
|
*/
|
||||||
void luaD_shrinkstack (lua_State *L) {
|
void luaD_shrinkstack (lua_State *L) {
|
||||||
int inuse = stackinuse(L);
|
int inuse = stackinuse(L);
|
||||||
int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3;
|
int max = (inuse > MAXSTACK / 3) ? MAXSTACK : inuse * 3;
|
||||||
/* if thread is currently not handling a stack overflow and its
|
/* if thread is currently not handling a stack overflow and its
|
||||||
size is larger than maximum "reasonable" size, shrink it */
|
size is larger than maximum "reasonable" size, shrink it */
|
||||||
if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) {
|
if (inuse <= MAXSTACK && stacksize(L) > max) {
|
||||||
int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2;
|
int nsize = (inuse > MAXSTACK / 2) ? MAXSTACK : inuse * 2;
|
||||||
luaD_reallocstack(L, nsize, 0); /* ok if that fails */
|
luaD_reallocstack(L, nsize, 0); /* ok if that fails */
|
||||||
}
|
}
|
||||||
else /* don't change stack */
|
else /* don't change stack */
|
||||||
@ -408,7 +423,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
|||||||
delta = ci->u.l.nextraargs + p->numparams + 1;
|
delta = ci->u.l.nextraargs + p->numparams + 1;
|
||||||
}
|
}
|
||||||
ci->func.p += delta; /* if vararg, back to virtual 'func' */
|
ci->func.p += delta; /* if vararg, back to virtual 'func' */
|
||||||
ftransfer = cast(unsigned short, firstres - ci->func.p);
|
ftransfer = cast_int(firstres - ci->func.p);
|
||||||
luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */
|
luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */
|
||||||
ci->func.p -= delta;
|
ci->func.p -= delta;
|
||||||
}
|
}
|
||||||
|
4
lstate.h
4
lstate.h
@ -207,8 +207,8 @@ struct CallInfo {
|
|||||||
int nyield; /* number of values yielded */
|
int nyield; /* number of values yielded */
|
||||||
int nres; /* number of values returned */
|
int nres; /* number of values returned */
|
||||||
struct { /* info about transferred values (for call/return hooks) */
|
struct { /* info about transferred values (for call/return hooks) */
|
||||||
unsigned short ftransfer; /* offset of first value transferred */
|
int ftransfer; /* offset of first value transferred */
|
||||||
unsigned short ntransfer; /* number of values transferred */
|
int ntransfer; /* number of values transferred */
|
||||||
} transferinfo;
|
} transferinfo;
|
||||||
} u2;
|
} u2;
|
||||||
short nresults; /* expected number of results from this function */
|
short nresults; /* expected number of results from this function */
|
||||||
|
4
lua.h
4
lua.h
@ -503,8 +503,8 @@ struct lua_Debug {
|
|||||||
unsigned char nparams;/* (u) number of parameters */
|
unsigned char nparams;/* (u) number of parameters */
|
||||||
char isvararg; /* (u) */
|
char isvararg; /* (u) */
|
||||||
char istailcall; /* (t) */
|
char istailcall; /* (t) */
|
||||||
unsigned short ftransfer; /* (r) index of first value transferred */
|
int ftransfer; /* (r) index of first value transferred */
|
||||||
unsigned short ntransfer; /* (r) number of transferred values */
|
int ntransfer; /* (r) number of transferred values */
|
||||||
char short_src[LUA_IDSIZE]; /* (S) */
|
char short_src[LUA_IDSIZE]; /* (S) */
|
||||||
/* private part */
|
/* private part */
|
||||||
struct CallInfo *i_ci; /* active function */
|
struct CallInfo *i_ci; /* active function */
|
||||||
|
@ -750,13 +750,13 @@
|
|||||||
@@ LUAI_MAXSTACK limits the size of the Lua stack.
|
@@ LUAI_MAXSTACK limits the size of the Lua stack.
|
||||||
** CHANGE it if you need a different limit. This limit is arbitrary;
|
** CHANGE it if you need a different limit. This limit is arbitrary;
|
||||||
** its only purpose is to stop Lua from consuming unlimited stack
|
** its only purpose is to stop Lua from consuming unlimited stack
|
||||||
** space (and to reserve some numbers for pseudo-indices).
|
** space and to reserve some numbers for pseudo-indices.
|
||||||
** (It must fit into max(size_t)/32 and max(int)/2.)
|
** (It must fit into max(int)/2.)
|
||||||
*/
|
*/
|
||||||
#if LUAI_IS32INT
|
#if 1000000 < (INT_MAX / 2)
|
||||||
#define LUAI_MAXSTACK 1000000
|
#define LUAI_MAXSTACK 1000000
|
||||||
#else
|
#else
|
||||||
#define LUAI_MAXSTACK 15000
|
#define LUAI_MAXSTACK (INT_MAX / 2u)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -4262,8 +4262,9 @@ you push the main function plus any arguments
|
|||||||
onto the empty stack of the thread.
|
onto the empty stack of the thread.
|
||||||
then you call @Lid{lua_resume},
|
then you call @Lid{lua_resume},
|
||||||
with @id{nargs} being the number of arguments.
|
with @id{nargs} being the number of arguments.
|
||||||
This call returns when the coroutine suspends or finishes its execution.
|
The function returns when the coroutine suspends,
|
||||||
When it returns,
|
finishes its execution, or raises an unprotected error.
|
||||||
|
When it returns without errors,
|
||||||
@id{*nresults} is updated and
|
@id{*nresults} is updated and
|
||||||
the top of the stack contains
|
the top of the stack contains
|
||||||
the @id{*nresults} values passed to @Lid{lua_yield}
|
the @id{*nresults} values passed to @Lid{lua_yield}
|
||||||
@ -4274,9 +4275,11 @@ or returned by the body function.
|
|||||||
without errors,
|
without errors,
|
||||||
or an error code in case of errors @see{statuscodes}.
|
or an error code in case of errors @see{statuscodes}.
|
||||||
In case of errors,
|
In case of errors,
|
||||||
the error object is on the top of the stack.
|
the error object is pushed on the top of the stack.
|
||||||
|
(In that case, @id{nresults} is not updated,
|
||||||
|
as its value would have to be 1 for the sole error object.)
|
||||||
|
|
||||||
To resume a coroutine,
|
To resume a suspended coroutine,
|
||||||
you remove the @id{*nresults} yielded values from its stack,
|
you remove the @id{*nresults} yielded values from its stack,
|
||||||
push the values to be passed as results from @id{yield},
|
push the values to be passed as results from @id{yield},
|
||||||
and then call @Lid{lua_resume}.
|
and then call @Lid{lua_resume}.
|
||||||
@ -4822,8 +4825,8 @@ typedef struct lua_Debug {
|
|||||||
unsigned char nparams; /* (u) number of parameters */
|
unsigned char nparams; /* (u) number of parameters */
|
||||||
char isvararg; /* (u) */
|
char isvararg; /* (u) */
|
||||||
char istailcall; /* (t) */
|
char istailcall; /* (t) */
|
||||||
unsigned short ftransfer; /* (r) index of first value transferred */
|
int ftransfer; /* (r) index of first value transferred */
|
||||||
unsigned short ntransfer; /* (r) number of transferred values */
|
int ntransfer; /* (r) number of transferred values */
|
||||||
char short_src[LUA_IDSIZE]; /* (S) */
|
char short_src[LUA_IDSIZE]; /* (S) */
|
||||||
/* private part */
|
/* private part */
|
||||||
@rep{other fields}
|
@rep{other fields}
|
||||||
|
Loading…
Reference in New Issue
Block a user