aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-11-03 16:34:36 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-11-03 16:34:36 -0300
commit58216600eba27d472de33dbb89e2f3e629bf8a59 (patch)
tree9504237097bb72548e5e7b66b753dc23056330a8
parent94cbe4651156a84dd9114d7daaa61acd050adbe0 (diff)
downloadlua-58216600eba27d472de33dbb89e2f3e629bf8a59.tar.gz
lua-58216600eba27d472de33dbb89e2f3e629bf8a59.tar.bz2
lua-58216600eba27d472de33dbb89e2f3e629bf8a59.zip
'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.
-rw-r--r--lauxlib.c72
-rw-r--r--lobject.c2
-rw-r--r--ltests.c2
3 files changed, 50 insertions, 26 deletions
diff --git a/lauxlib.c b/lauxlib.c
index cbe9ed31..73504389 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
283 283
284 284
285LUALIB_API int luaL_execresult (lua_State *L, int stat) { 285LUALIB_API int luaL_execresult (lua_State *L, int stat) {
286 const char *what = "exit"; /* type of termination */
287 if (stat != 0 && errno != 0) /* error with an 'errno'? */ 286 if (stat != 0 && errno != 0) /* error with an 'errno'? */
288 return luaL_fileresult(L, 0, NULL); 287 return luaL_fileresult(L, 0, NULL);
289 else { 288 else {
289 const char *what = "exit"; /* type of termination */
290 l_inspectstat(stat, what); /* interpret result */ 290 l_inspectstat(stat, what); /* interpret result */
291 if (*what == 'e' && stat == 0) /* successful termination? */ 291 if (*what == 'e' && stat == 0) /* successful termination? */
292 lua_pushboolean(L, 1); 292 lua_pushboolean(L, 1);
@@ -1006,43 +1006,67 @@ static int panic (lua_State *L) {
1006 1006
1007 1007
1008/* 1008/*
1009** Emit a warning. '*warnstate' means: 1009** Warning functions:
1010** 0 - warning system is off; 1010** warnfoff: warning system is off
1011** 1 - ready to start a new message; 1011** warnfon: ready to start a new message
1012** 2 - previous message is to be continued. 1012** warnfcont: previous message is to be continued
1013*/ 1013*/
1014static void warnf (void *ud, const char *message, int tocont) { 1014static void warnfoff (void *ud, const char *message, int tocont);
1015 int *warnstate = (int *)ud; 1015static void warnfon (void *ud, const char *message, int tocont);
1016 if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */ 1016static void warnfcont (void *ud, const char *message, int tocont);
1017 if (strcmp(message, "@off") == 0) 1017
1018 *warnstate = 0; 1018
1019 else if (strcmp(message, "@on") == 0) 1019/*
1020 *warnstate = 1; 1020** Check whether message is a control message. If so, execute the
1021 return; 1021** control or ignore it if unknown.
1022*/
1023static int checkcontrol (lua_State *L, const char *message, int tocont) {
1024 if (tocont || *(message++) != '@') /* not a control message? */
1025 return 0;
1026 else {
1027 if (strcmp(message, "off") == 0)
1028 lua_setwarnf(L, warnfoff, L); /* turn warnings off */
1029 else if (strcmp(message, "on") == 0)
1030 lua_setwarnf(L, warnfon, L); /* turn warnings on */
1031 return 1; /* it was a control message */
1022 } 1032 }
1023 else if (*warnstate == 0) /* warnings off? */ 1033}
1024 return; 1034
1025 if (*warnstate == 1) /* previous message was the last? */ 1035
1026 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ 1036static void warnfoff (void *ud, const char *message, int tocont) {
1037 checkcontrol((lua_State *)ud, message, tocont);
1038}
1039
1040
1041/*
1042** Writes the message and handle 'tocont', finishing the message
1043** if needed and setting the next warn function.
1044*/
1045static void warnfcont (void *ud, const char *message, int tocont) {
1046 lua_State *L = (lua_State *)ud;
1027 lua_writestringerror("%s", message); /* write message */ 1047 lua_writestringerror("%s", message); /* write message */
1028 if (tocont) /* not the last part? */ 1048 if (tocont) /* not the last part? */
1029 *warnstate = 2; /* to be continued */ 1049 lua_setwarnf(L, warnfcont, L); /* to be continued */
1030 else { /* last part */ 1050 else { /* last part */
1031 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ 1051 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
1032 *warnstate = 1; /* ready to start a new message */ 1052 lua_setwarnf(L, warnfon, L); /* next call is a new message */
1033 } 1053 }
1034} 1054}
1035 1055
1036 1056
1057static void warnfon (void *ud, const char *message, int tocont) {
1058 if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */
1059 return; /* nothing else to be done */
1060 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
1061 warnfcont(ud, message, tocont); /* finish processing */
1062}
1063
1064
1037LUALIB_API lua_State *luaL_newstate (void) { 1065LUALIB_API lua_State *luaL_newstate (void) {
1038 lua_State *L = lua_newstate(l_alloc, NULL); 1066 lua_State *L = lua_newstate(l_alloc, NULL);
1039 if (L) { 1067 if (L) {
1040 int *warnstate; /* space for warning state */
1041 lua_atpanic(L, &panic); 1068 lua_atpanic(L, &panic);
1042 warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0); 1069 lua_setwarnf(L, warnfoff, L); /* default is warnings off */
1043 luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
1044 *warnstate = 0; /* default is warnings off */
1045 lua_setwarnf(L, warnf, warnstate);
1046 } 1070 }
1047 return L; 1071 return L;
1048} 1072}
diff --git a/lobject.c b/lobject.c
index f8ea917a..0e504be0 100644
--- a/lobject.c
+++ b/lobject.c
@@ -258,7 +258,7 @@ static const char *l_str2d (const char *s, lua_Number *result) {
258 if (endptr == NULL) { /* failed? may be a different locale */ 258 if (endptr == NULL) { /* failed? may be a different locale */
259 char buff[L_MAXLENNUM + 1]; 259 char buff[L_MAXLENNUM + 1];
260 const char *pdot = strchr(s, '.'); 260 const char *pdot = strchr(s, '.');
261 if (strlen(s) > L_MAXLENNUM || pdot == NULL) 261 if (pdot == NULL || strlen(s) > L_MAXLENNUM)
262 return NULL; /* string too long or no dot; fail */ 262 return NULL; /* string too long or no dot; fail */
263 strcpy(buff, s); /* copy string to buffer */ 263 strcpy(buff, s); /* copy string to buffer */
264 buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ 264 buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
diff --git a/ltests.c b/ltests.c
index 7e3a389a..2020131f 100644
--- a/ltests.c
+++ b/ltests.c
@@ -863,7 +863,7 @@ static int alloc_failnext (lua_State *L) {
863 l_memcontrol.failnext = 1; 863 l_memcontrol.failnext = 1;
864 return 0; 864 return 0;
865} 865}
866 866
867 867
868static int settrick (lua_State *L) { 868static int settrick (lua_State *L) {
869 if (ttisnil(obj_at(L, 1))) 869 if (ttisnil(obj_at(L, 1)))