'luaL_newstate' should not allocate extra memory
The allocation of a userdata for the state of the warn system can cause a panic if it fails; 'luaL_ref' also can fail. This commit re-implements the warn system so that it does not need an explicit state. Instead, the system uses different functions to represent the different states.
This commit is contained in:
72
lauxlib.c
72
lauxlib.c
@@ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
|
|||||||
|
|
||||||
|
|
||||||
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
|
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
|
||||||
const char *what = "exit"; /* type of termination */
|
|
||||||
if (stat != 0 && errno != 0) /* error with an 'errno'? */
|
if (stat != 0 && errno != 0) /* error with an 'errno'? */
|
||||||
return luaL_fileresult(L, 0, NULL);
|
return luaL_fileresult(L, 0, NULL);
|
||||||
else {
|
else {
|
||||||
|
const char *what = "exit"; /* type of termination */
|
||||||
l_inspectstat(stat, what); /* interpret result */
|
l_inspectstat(stat, what); /* interpret result */
|
||||||
if (*what == 'e' && stat == 0) /* successful termination? */
|
if (*what == 'e' && stat == 0) /* successful termination? */
|
||||||
lua_pushboolean(L, 1);
|
lua_pushboolean(L, 1);
|
||||||
@@ -1006,43 +1006,67 @@ static int panic (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Emit a warning. '*warnstate' means:
|
** Warning functions:
|
||||||
** 0 - warning system is off;
|
** warnfoff: warning system is off
|
||||||
** 1 - ready to start a new message;
|
** warnfon: ready to start a new message
|
||||||
** 2 - previous message is to be continued.
|
** warnfcont: previous message is to be continued
|
||||||
*/
|
*/
|
||||||
static void warnf (void *ud, const char *message, int tocont) {
|
static void warnfoff (void *ud, const char *message, int tocont);
|
||||||
int *warnstate = (int *)ud;
|
static void warnfon (void *ud, const char *message, int tocont);
|
||||||
if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
|
static void warnfcont (void *ud, const char *message, int tocont);
|
||||||
if (strcmp(message, "@off") == 0)
|
|
||||||
*warnstate = 0;
|
|
||||||
else if (strcmp(message, "@on") == 0)
|
/*
|
||||||
*warnstate = 1;
|
** Check whether message is a control message. If so, execute the
|
||||||
return;
|
** control or ignore it if unknown.
|
||||||
|
*/
|
||||||
|
static int checkcontrol (lua_State *L, const char *message, int tocont) {
|
||||||
|
if (tocont || *(message++) != '@') /* not a control message? */
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
if (strcmp(message, "off") == 0)
|
||||||
|
lua_setwarnf(L, warnfoff, L); /* turn warnings off */
|
||||||
|
else if (strcmp(message, "on") == 0)
|
||||||
|
lua_setwarnf(L, warnfon, L); /* turn warnings on */
|
||||||
|
return 1; /* it was a control message */
|
||||||
}
|
}
|
||||||
else if (*warnstate == 0) /* warnings off? */
|
}
|
||||||
return;
|
|
||||||
if (*warnstate == 1) /* previous message was the last? */
|
|
||||||
lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
|
static void warnfoff (void *ud, const char *message, int tocont) {
|
||||||
|
checkcontrol((lua_State *)ud, message, tocont);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Writes the message and handle 'tocont', finishing the message
|
||||||
|
** if needed and setting the next warn function.
|
||||||
|
*/
|
||||||
|
static void warnfcont (void *ud, const char *message, int tocont) {
|
||||||
|
lua_State *L = (lua_State *)ud;
|
||||||
lua_writestringerror("%s", message); /* write message */
|
lua_writestringerror("%s", message); /* write message */
|
||||||
if (tocont) /* not the last part? */
|
if (tocont) /* not the last part? */
|
||||||
*warnstate = 2; /* to be continued */
|
lua_setwarnf(L, warnfcont, L); /* to be continued */
|
||||||
else { /* last part */
|
else { /* last part */
|
||||||
lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
|
lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
|
||||||
*warnstate = 1; /* ready to start a new message */
|
lua_setwarnf(L, warnfon, L); /* next call is a new message */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void warnfon (void *ud, const char *message, int tocont) {
|
||||||
|
if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */
|
||||||
|
return; /* nothing else to be done */
|
||||||
|
lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
|
||||||
|
warnfcont(ud, message, tocont); /* finish processing */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUALIB_API lua_State *luaL_newstate (void) {
|
LUALIB_API lua_State *luaL_newstate (void) {
|
||||||
lua_State *L = lua_newstate(l_alloc, NULL);
|
lua_State *L = lua_newstate(l_alloc, NULL);
|
||||||
if (L) {
|
if (L) {
|
||||||
int *warnstate; /* space for warning state */
|
|
||||||
lua_atpanic(L, &panic);
|
lua_atpanic(L, &panic);
|
||||||
warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0);
|
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
|
||||||
luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
|
|
||||||
*warnstate = 0; /* default is warnings off */
|
|
||||||
lua_setwarnf(L, warnf, warnstate);
|
|
||||||
}
|
}
|
||||||
return L;
|
return L;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ static const char *l_str2d (const char *s, lua_Number *result) {
|
|||||||
if (endptr == NULL) { /* failed? may be a different locale */
|
if (endptr == NULL) { /* failed? may be a different locale */
|
||||||
char buff[L_MAXLENNUM + 1];
|
char buff[L_MAXLENNUM + 1];
|
||||||
const char *pdot = strchr(s, '.');
|
const char *pdot = strchr(s, '.');
|
||||||
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
|
if (pdot == NULL || strlen(s) > L_MAXLENNUM)
|
||||||
return NULL; /* string too long or no dot; fail */
|
return NULL; /* string too long or no dot; fail */
|
||||||
strcpy(buff, s); /* copy string to buffer */
|
strcpy(buff, s); /* copy string to buffer */
|
||||||
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
|
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
|
||||||
|
|||||||
Reference in New Issue
Block a user