mirror of
https://github.com/lua/lua
synced 2024-12-26 20:29:43 +03:00
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:
parent
70d6975018
commit
20d42ccaae
2
lapi.c
2
lapi.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
3
ldebug.c
3
ldebug.c
@ -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--;
|
||||
|
37
lobject.c
37
lobject.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user