No errors in 'luaO_pushvfstring'

Any call to 'va_start' must have a corresponding call to 'va_end';
so, functions called between them (luaO_pushvfstring in particular)
cannot raise errors.
This commit is contained in:
Roberto Ierusalimschy 2024-09-20 15:56:39 -03:00
parent 70d6975018
commit 20d42ccaae
5 changed files with 45 additions and 24 deletions

2
lapi.c
View File

@ -587,6 +587,8 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
ret = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
luaC_checkGC(L);
if (ret == NULL) /* error? */
luaD_throw(L, LUA_ERRMEM);
lua_unlock(L);
return ret;
}

View File

@ -225,7 +225,7 @@ LUALIB_API void luaL_where (lua_State *L, int level) {
/*
** Again, the use of 'lua_pushvfstring' ensures this function does
** not need reserved stack space when called. (At worst, it generates
** an error with "stack overflow" instead of the given message.)
** a memory error instead of the given message.)
*/
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
va_list argp;

View File

@ -847,7 +847,8 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
va_end(argp);
if (isLua(ci)) { /* if Lua function, add source:line information */
if (msg != NULL && isLua(ci)) { /* Lua function? (and no error) */
/* add source:line information */
luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */
L->top.p--;

View File

@ -480,7 +480,7 @@ void luaO_tostring (lua_State *L, TValue *obj) {
#define BUFVFS cast_uint(LUA_IDSIZE + MAXNUMBER2STR + 95)
/*
** Buffer used by 'luaO_pushvfstring'. 'err' signals any error while
** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while
** building result (memory error [1] or buffer overflow [2]).
*/
typedef struct BuffFS {
@ -512,9 +512,14 @@ static void pushbuff (lua_State *L, void *ud) {
case 1:
luaD_throw(L, LUA_ERRMEM);
break;
case 2:
luaG_runerror(L, "buffer overflow");
break;
case 2: /* length overflow: Add "..." at the end of result */
if (buff->buffsize - buff->blen < 3)
strcpy(buff->b + buff->blen - 3, "..."); /* 'blen' must be > 3 */
else { /* there is enough space left for the "..." */
strcpy(buff->b + buff->blen, "...");
buff->blen += 3;
}
/* FALLTHROUGH */
default: { /* no errors */
TString *ts = luaS_newlstr(L, buff->b, buff->blen);
setsvalue2s(L, L->top.p, ts);
@ -527,8 +532,10 @@ static void pushbuff (lua_State *L, void *ud) {
static const char *clearbuff (BuffFS *buff) {
lua_State *L = buff->L;
const char *res;
pushbuff(L, buff);
res = getstr(tsvalue(s2v(L->top.p - 1)));
if (luaD_rawrunprotected(L, pushbuff, buff) != LUA_OK) /* errors? */
res = NULL; /* error message is on the top of the stack */
else
res = getstr(tsvalue(s2v(L->top.p - 1)));
if (buff->b != buff->space) /* using dynamic buffer? */
luaM_freearray(L, buff->b, buff->buffsize); /* free it */
return res;
@ -536,12 +543,14 @@ static const char *clearbuff (BuffFS *buff) {
static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
size_t left = buff->buffsize - buff->blen; /* space left in the buffer */
if (buff->err) /* do nothing else after an error */
return;
if (slen > buff->buffsize - buff->blen) {
/* new string doesn't fit into current buffer */
if (slen > left) { /* new string doesn't fit into current buffer? */
if (slen > ((MAX_SIZE/2) - buff->blen)) { /* overflow? */
buff->err = 2;
memcpy(buff->b + buff->blen, str, left); /* copy what it can */
buff->blen = buff->buffsize;
buff->err = 2; /* doesn't add anything else */
return;
}
else {
@ -552,13 +561,13 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
: luaM_reallocvector(buff->L, buff->b, buff->buffsize, newsize,
char);
if (newb == NULL) { /* allocation error? */
buff->err = 1;
buff->err = 1; /* signal a memory error */
return;
}
if (buff->b == buff->space)
if (buff->b == buff->space) /* new buffer (not reallocated)? */
memcpy(newb, buff->b, buff->blen); /* copy previous content */
buff->b = newb;
buff->buffsize = newsize;
buff->b = newb; /* set new (larger) buffer... */
buff->buffsize = newsize; /* ...and its new size */
}
}
memcpy(buff->b + buff->blen, str, slen); /* copy new content */
@ -651,6 +660,8 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
if (msg == NULL) /* error? */
luaD_throw(L, LUA_ERRMEM);
return msg;
}

View File

@ -3974,7 +3974,7 @@ Lua will call @id{falloc} before raising the error.
@APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);|
@apii{0,1,v}
@apii{0,1,m}
Pushes onto the stack a formatted string
and returns a pointer to this string @see{constchar}.
@ -3997,9 +3997,6 @@ The conversion specifiers can only be
@Char{%c} (inserts an @T{int} as a one-byte character), and
@Char{%U} (inserts an @T{unsigned long} as a @x{UTF-8} byte sequence).
This function may raise errors due to memory overflow
or an invalid conversion specifier.
}
@APIEntry{void lua_pushglobaltable (lua_State *L);|
@ -4104,10 +4101,14 @@ onto the stack.
const char *lua_pushvfstring (lua_State *L,
const char *fmt,
va_list argp);|
@apii{0,1,v}
@apii{0,1,-}
Equivalent to @Lid{lua_pushfstring}, except that it receives a @id{va_list}
instead of a variable number of arguments.
Equivalent to @Lid{lua_pushfstring},
except that it receives a @id{va_list}
instead of a variable number of arguments,
and it does not raise errors.
Instead, in case of errors it pushes the error message
and returns @id{NULL}.
}
@ -5636,6 +5637,7 @@ It is defined as the following macro:
}
It @N{returns 0} (@Lid{LUA_OK}) if there are no errors,
or 1 in case of errors.
(Except for out-of-memory errors, which are raised.)
}
@ -5800,7 +5802,7 @@ The first line in the file is ignored if it starts with a @T{#}.
The string @id{mode} works as in the function @Lid{lua_load}.
This function returns the same results as @Lid{lua_load}
This function returns the same results as @Lid{lua_load},
or @Lid{LUA_ERRFILE} for file-related errors.
As @Lid{lua_load}, this function only loads the chunk;
@ -9260,7 +9262,7 @@ the script is compiled as a variadic function.
In interactive mode,
Lua repeatedly prompts and waits for a line.
After reading a line,
Lua first try to interpret the line as an expression.
Lua first tries to interpret the line as an expression.
If it succeeds, it prints its value.
Otherwise, it interprets the line as a chunk.
If you write an incomplete chunk,
@ -9424,6 +9426,11 @@ instead, there is a new option @Lid{LUA_GCPARAM} to that end.
Moreover, there were some changes in the parameters themselves.
}
@item{
The function @Lid{lua_pushvfstring} now reports errors,
instead of raising them.
}
}
}