Compare commits

..

5 Commits
rc ... v5.5.0

Author SHA1 Message Date
Roberto I
a5522f06d2 GC checks stack space before running finalizer
If the stack does not have some minimum available space, the GC defers
calling a finalizer until the next cycle. That avoids errors while
running a finalizer that the programmer cannot control.
2025-12-13 16:16:59 -03:00
Roberto I
3d03ae5bd6 'luaL_newstate' starts state with warnings on
It is easier to forget to turn them on then to turn them off.
2025-12-13 11:00:30 -03:00
Roberto I
82d721a855 Format adjust in the manual
Lists in inline code don't get a space after commas. (That keeps the
code more compact and avoids line breaks in the middle of the code.)
2025-12-10 10:35:05 -03:00
Roberto I
104b0fc700 Details
- Avoid fixing name "_ENV" in the code
- Small improvements in the manual
2025-12-08 13:09:47 -03:00
Roberto I
8164d09338 Wrong assert in 'luaK_indexed' 2025-12-08 11:08:12 -03:00
8 changed files with 50 additions and 34 deletions

View File

@@ -1185,7 +1185,7 @@ LUALIB_API lua_State *(luaL_newstate) (void) {
lua_State *L = lua_newstate(luaL_alloc, NULL, luaL_makeseed(NULL));
if (l_likely(L)) {
lua_atpanic(L, &panic);
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
lua_setwarnf(L, warnfon, L);
}
return L;
}

View File

@@ -1370,9 +1370,11 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
}
else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */
lua_assert(t->u.ind.t == fs->f->numparams);
t->u.ind.t = cast_byte(t->u.var.ridx);
fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* register */
int kreg = luaK_exp2anyreg(fs, k); /* put key in some register */
lu_byte vreg = cast_byte(t->u.var.ridx); /* register with vararg param. */
lua_assert(vreg == fs->f->numparams);
t->u.ind.t = vreg; /* (avoid a direct assignment; values may overlap) */
fillidxk(t, kreg, VVARGIND); /* 't' represents 'vararg[k]' */
}
else {
/* register index of the table */

11
ldo.c
View File

@@ -220,6 +220,17 @@ l_noret luaD_errerr (lua_State *L) {
}
/*
** Check whether stack has enough space to run a simple function (such
** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack and
** 2 slots in the C stack.
*/
int luaD_checkminstack (lua_State *L) {
return ((stacksize(L) < MAXSTACK - BASIC_STACK_SIZE) &&
(getCcalls(L) < LUAI_MAXCCALLS - 2));
}
/*
** In ISO C, any pointer use after the pointer has been deallocated is
** undefined behavior. So, before a stack reallocation, all pointers

1
ldo.h
View File

@@ -89,6 +89,7 @@ LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
LUAI_FUNC void luaD_inctop (lua_State *L);
LUAI_FUNC int luaD_checkminstack (lua_State *L);
LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode);
LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode);

7
lgc.c
View File

@@ -1293,7 +1293,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
correctgraylists(g);
checkSizes(L, g);
g->gcstate = GCSpropagate; /* skip restart */
if (!g->gcemergency)
if (!g->gcemergency && luaD_checkminstack(L))
callallpendingfinalizers(L);
}
@@ -1667,12 +1667,13 @@ static l_mem singlestep (lua_State *L, int fast) {
break;
}
case GCScallfin: { /* call finalizers */
if (g->tobefnz && !g->gcemergency) {
if (g->tobefnz && !g->gcemergency && luaD_checkminstack(L)) {
g->gcstopem = 0; /* ok collections during finalizers */
GCTM(L); /* call one finalizer */
stepresult = CWUFIN;
}
else { /* emergency mode or no more finalizers */
else { /* no more finalizers or emergency mode or no enough stack
to run finalizers */
g->gcstate = GCSpause; /* finish collection */
stepresult = step2pause;
}

View File

@@ -505,8 +505,8 @@ static void buildglobal (LexState *ls, TString *varname, expdesc *var) {
init_exp(var, VGLOBAL, -1); /* global by default */
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
if (var->k == VGLOBAL)
luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
getstr(varname));
luaK_semerror(ls, "%s is global when accessing variable '%s'",
LUA_ENV, getstr(varname));
luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
codestring(&key, varname); /* key is variable name */
luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */

3
lua.c
View File

@@ -349,6 +349,7 @@ static int collectargs (char **argv, int *first) {
*/
static int runargs (lua_State *L, char **argv, int n) {
int i;
lua_warning(L, "@off", 0); /* by default, Lua stand-alone has warnings off */
for (i = 1; i < n; i++) {
int option = argv[i][1];
lua_assert(argv[i][0] == '-'); /* already checked */
@@ -725,7 +726,7 @@ static int pmain (lua_State *L) {
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
return 0; /* error running LUA_INIT */
}
if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */
if (!runargs(L, argv, optlim)) /* execute arguments -e, -l, and -W */
return 0; /* something failed */
if (script > 0) { /* execute main script (if there is one) */
if (handle_script(L, argv + script) != LUA_OK)

View File

@@ -107,7 +107,7 @@ for small machines and embedded systems.
Unless stated otherwise,
any overflow when manipulating integer values @def{wrap around},
according to the usual rules of two-complement arithmetic.
according to the usual rules of two's complement arithmetic.
(In other words,
the actual result is the unique representable integer
that is equal modulo @M{2@sp{n}} to the mathematical result,
@@ -2091,12 +2091,12 @@ Note that keys that are not positive integers
do not interfere with borders.
A table with exactly one border is called a @def{sequence}.
For instance, the table @T{{10, 20, 30, 40, 50}} is a sequence,
For instance, the table @T{{10,20,30,40,50}} is a sequence,
as it has only one border (5).
The table @T{{10, 20, 30, nil, 50}} has two borders (3 and 5),
The table @T{{10,20,30,nil,50}} has two borders (3 and 5),
and therefore it is not a sequence.
(The @nil at index 4 is called a @emphx{hole}.)
The table @T{{nil, 20, 30, nil, nil, 60, nil}}
The table @T{{nil,20,30,nil,nil,60,nil}}
has three borders (0, 3, and 6),
so it is not a sequence, too.
The table @T{{}} is a sequence with border 0.
@@ -2449,22 +2449,22 @@ These are the places where Lua expects a list of expressions:
@description{
@item{A @rw{return} statement,
for instance @T{return e1, e2, e3} @see{control}.}
for instance @T{return e1,e2,e3} @see{control}.}
@item{A table constructor,
for instance @T{{e1, e2, e3}} @see{tableconstructor}.}
for instance @T{{e1,e2,e3}} @see{tableconstructor}.}
@item{The arguments of a function call,
for instance @T{foo(e1, e2, e3)} @see{functioncall}.}
for instance @T{foo(e1,e2,e3)} @see{functioncall}.}
@item{A multiple assignment,
for instance @T{a , b, c = e1, e2, e3} @see{assignment}.}
for instance @T{a,b,c = e1,e2,e3} @see{assignment}.}
@item{A local or global declaration,
which is similar to a multiple assignment.}
@item{The initial values in a generic @rw{for} loop,
for instance @T{for k in e1, e2, e3 do ... end} @see{for}.}
for instance @T{for k in e1,e2,e3 do ... end} @see{for}.}
}
In the last four cases,
@@ -2501,7 +2501,7 @@ we recommend assigning the vararg expression
to a single variable and using that variable
in its place.
Here are some examples of uses of mutlres expressions.
Here are some examples of uses of multires expressions.
In all cases, when the construction needs
@Q{the n-th result} and there is no such result,
it uses a @nil.
@@ -3107,7 +3107,7 @@ void *luaL_alloc (void *ud, void *ptr, size_t osize,
}
Note that @N{ISO C} ensures
that @T{free(NULL)} has no effect and that
@T{realloc(NULL, size)} is equivalent to @T{malloc(size)}.
@T{realloc(NULL,size)} is equivalent to @T{malloc(size)}.
}
@@ -3640,9 +3640,9 @@ because a pseudo-index is not an actual stack position.
The type of integers in Lua.
By default this type is @id{long long},
(usually a 64-bit two-complement integer),
(usually a 64-bit two's complement integer),
but that can be changed to @id{long} or @id{int}
(usually a 32-bit two-complement integer).
(usually a 32-bit two's complement integer).
(See @id{LUA_INT_TYPE} in @id{luaconf.h}.)
Lua also defines the constants
@@ -3879,7 +3879,7 @@ is a seed for the hashing of strings.
@apii{0,1,m}
Creates a new empty table and pushes it onto the stack.
It is equivalent to @T{lua_createtable(L, 0, 0)}.
It is equivalent to @T{lua_createtable(L,0,0)}.
}
@@ -5439,7 +5439,7 @@ the auxiliary library provides higher-level functions for some
common tasks.
All functions and types from the auxiliary library
are defined in header file @id{lauxlib.h} and
are defined in the header file @id{lauxlib.h} and
have a prefix @id{luaL_}.
All functions in the auxiliary library are built on
@@ -5583,7 +5583,7 @@ Its pattern of use is as follows:
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
@item{Then initialize it with a call @T{luaL_buffinit(L, &b)}.}
@item{Then initialize it with a call @T{luaL_buffinit(L,&b)}.}
@item{
Then add string pieces to the buffer calling any of
@@ -5604,12 +5604,12 @@ you can use the buffer like this:
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
@item{Then initialize it and preallocate a space of
size @id{sz} with a call @T{luaL_buffinitsize(L, &b, sz)}.}
size @id{sz} with a call @T{luaL_buffinitsize(L,&b,sz)}.}
@item{Then produce the string into that space.}
@item{
Finish by calling @T{luaL_pushresultsize(&b, sz)},
Finish by calling @T{luaL_pushresultsize(&b,sz)},
where @id{sz} is the total size of the resulting string
copied into that space (which may be less than or
equal to the preallocated size).
@@ -6214,7 +6214,7 @@ You should not manually set integer keys in the table
after the first use of @Lid{luaL_ref}.
You can retrieve an object referred by the reference @id{r}
by calling @T{lua_rawgeti(L, t, r)} or @T{lua_geti(L, t, r)}.
by calling @T{lua_rawgeti(L,t,r)} or @T{lua_geti(L,t,r)}.
The function @Lid{luaL_unref} frees a reference.
If the object on the top of the stack is @nil,
@@ -6492,7 +6492,7 @@ the host program can call the function @Lid{luaL_openlibs}.
Alternatively,
the host can select which libraries to open,
by using @Lid{luaL_openselectedlibs}.
Both functions are defined in the header file @id{lualib.h}.
Both functions are declared in the header file @id{lualib.h}.
@index{lualib.h}
The stand-alone interpreter @id{lua} @see{lua-sa}
@@ -7744,7 +7744,7 @@ If @id{j} is absent, then it is assumed to be equal to @num{-1}
In particular,
the call @T{string.sub(s,1,j)} returns a prefix of @id{s}
with length @id{j},
and @T{string.sub(s, -i)} (for a positive @id{i})
and @T{string.sub(s,-i)} (for a positive @id{i})
returns a suffix of @id{s}
with length @id{i}.
@@ -8180,7 +8180,7 @@ the function returns @fail.
A negative @id{n} gets characters before position @id{i}.
The default for @id{i} is 1 when @id{n} is non-negative
and @T{#s + 1} otherwise,
so that @T{utf8.offset(s, -n)} gets the offset of the
so that @T{utf8.offset(s,-n)} gets the offset of the
@id{n}-th character from the end of the string.
As a special case,
@@ -8233,7 +8233,7 @@ the table will have; its default is zero.
Inserts element @id{value} at position @id{pos} in @id{list},
shifting up the elements
@T{list[pos], list[pos+1], @Cdots, list[#list]}.
@T{list[pos],list[pos+1],@Cdots,list[#list]}.
The default value for @id{pos} is @T{#list+1},
so that a call @T{table.insert(t,x)} inserts @id{x} at the end
of the list @id{t}.
@@ -8271,7 +8271,7 @@ Removes from @id{list} the element at position @id{pos},
returning the value of the removed element.
When @id{pos} is an integer between 1 and @T{#list},
it shifts down the elements
@T{list[pos+1], list[pos+2], @Cdots, list[#list]}
@T{list[pos+1],list[pos+2],@Cdots,list[#list]}
and erases element @T{list[#list]};
The index @id{pos} can also be 0 when @T{#list} is 0,
or @T{#list + 1}.