ソースを参照

'luaD_seterrorobj' should not raise errors

This function can be called unprotected, so it should not raise any
kind of errors. (It could raise a memory-allocation error when creating
a message).
Roberto Ierusalimschy 4 ヶ月 前
コミット
c931d86e98
5 ファイル変更25 行追加22 行削除
  1. 4 0
      ldebug.c
  2. 17 19
      ldo.c
  3. 1 0
      ldo.h
  4. 1 1
      lstate.c
  5. 2 2
      testes/errors.lua

+ 4 - 0
ldebug.c

@@ -832,6 +832,10 @@ l_noret luaG_errormsg (lua_State *L) {
     L->top.p++;  /* assume EXTRA_STACK */
     luaD_callnoyield(L, L->top.p - 2, 1);  /* call it */
   }
+  if (ttisnil(s2v(L->top.p - 1))) {  /* error object is nil? */
+    /* change it to a proper message */
+    setsvalue2s(L, L->top.p - 1, luaS_newliteral(L, "<no error object>"));
+  }
   luaD_throw(L, LUA_ERRRUN);
 }
 

+ 17 - 19
ldo.c

@@ -102,24 +102,13 @@ struct lua_longjmp {
 
 
 void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) {
-  switch (errcode) {
-    case LUA_ERRMEM: {  /* memory error? */
-      setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
-      break;
-    }
-    case LUA_ERRERR: {
-      setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
-      break;
-    }
-    default: {
-      lua_assert(errorstatus(errcode));  /* must be a real error */
-      if (!ttisnil(s2v(L->top.p - 1))) {  /* error object is not nil? */
-        setobjs2s(L, oldtop, L->top.p - 1);  /* move it to 'oldtop' */
-      }
-      else  /* change it to a proper message */
-        setsvalue2s(L, oldtop, luaS_newliteral(L, "<error object is nil>"));
-      break;
-    }
+  if (errcode == LUA_ERRMEM) {  /* memory error? */
+    setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
+  }
+  else {
+    lua_assert(errorstatus(errcode));  /* must be a real error */
+    lua_assert(!ttisnil(s2v(L->top.p - 1)));  /* with a non-nil object */
+    setobjs2s(L, oldtop, L->top.p - 1);  /* move it to 'oldtop' */
   }
   L->top.p = oldtop + 1;  /* top goes back to old top plus error object */
 }
@@ -190,6 +179,15 @@ TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
 #define ERRORSTACKSIZE	(MAXSTACK + STACKERRSPACE)
 
 
+/* raise an error while running the message handler */
+l_noret luaD_errerr (lua_State *L) {
+  TString *msg = luaS_newliteral(L, "error in error handling");
+  setsvalue2s(L, L->top.p, msg);
+  L->top.p++;  /* assume EXTRA_STACK */
+  luaD_throw(L, LUA_ERRERR);
+}
+
+
 /*
 ** In ISO C, any pointer use after the pointer has been deallocated is
 ** undefined behavior. So, before a stack reallocation, all pointers
@@ -317,7 +315,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
        a stack error; cannot grow further than that. */
     lua_assert(stacksize(L) == ERRORSTACKSIZE);
     if (raiseerror)
-      luaD_throw(L, LUA_ERRERR);  /* error inside message handler */
+      luaD_errerr(L);  /* error inside message handler */
     return 0;  /* if not 'raiseerror', just signal it */
   }
   else if (n < MAXSTACK) {  /* avoids arithmetic overflows */

+ 1 - 0
ldo.h

@@ -67,6 +67,7 @@
 /* type of protected functions, to be ran by 'runprotected' */
 typedef void (*Pfunc) (lua_State *L, void *ud);
 
+LUAI_FUNC l_noret luaD_errerr (lua_State *L);
 LUAI_FUNC void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop);
 LUAI_FUNC TStatus luaD_protectedparser (lua_State *L, ZIO *z,
                                                   const char *name,

+ 1 - 1
lstate.c

@@ -132,7 +132,7 @@ void luaE_checkcstack (lua_State *L) {
   if (getCcalls(L) == LUAI_MAXCCALLS)
     luaG_runerror(L, "C stack overflow");
   else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
-    luaD_throw(L, LUA_ERRERR);  /* error while handling stack error */
+    luaD_errerr(L);  /* error while handling stack error */
 }
 
 

+ 2 - 2
testes/errors.lua

@@ -46,7 +46,7 @@ end
 assert(doit("error('hi', 0)") == 'hi')
 
 -- test nil error message
-assert(doit("error()") == "<error object is nil>")
+assert(doit("error()") == "<no error object>")
 
 
 -- test common errors/errors that crashed in the past
@@ -614,7 +614,7 @@ do
   assert(not res and msg == t)
 
   res, msg = pcall(function () error(nil) end)
-  assert(not res and msg == "<error object is nil>")
+  assert(not res and msg == "<no error object>")
 
   local function f() error{msg='x'} end
   res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)