diff options
| -rw-r--r-- | lauxlib.c | 9 | ||||
| -rw-r--r-- | ldebug.c | 5 | ||||
| -rw-r--r-- | ldo.c | 4 | ||||
| -rw-r--r-- | lstring.c | 2 | ||||
| -rw-r--r-- | ltests.c | 5 | ||||
| -rw-r--r-- | lvm.c | 2 | ||||
| -rw-r--r-- | manual/manual.of | 4 | ||||
| -rw-r--r-- | testes/coroutine.lua | 8 |
8 files changed, 27 insertions, 12 deletions
| @@ -1043,9 +1043,14 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { | |||
| 1043 | } | 1043 | } |
| 1044 | 1044 | ||
| 1045 | 1045 | ||
| 1046 | /* | ||
| 1047 | ** Standard panic funcion just prints an error message. The test | ||
| 1048 | ** with 'lua_type' avoids possible memory errors in 'lua_tostring'. | ||
| 1049 | */ | ||
| 1046 | static int panic (lua_State *L) { | 1050 | static int panic (lua_State *L) { |
| 1047 | const char *msg = lua_tostring(L, -1); | 1051 | const char *msg = (lua_type(L, -1) == LUA_TSTRING) |
| 1048 | if (msg == NULL) msg = "error object is not a string"; | 1052 | ? lua_tostring(L, -1) |
| 1053 | : "error object is not a string"; | ||
| 1049 | lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", | 1054 | lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", |
| 1050 | msg); | 1055 | msg); |
| 1051 | return 0; /* return to Lua to abort */ | 1056 | return 0; /* return to Lua to abort */ |
| @@ -927,12 +927,12 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { | |||
| 927 | } | 927 | } |
| 928 | pc++; /* reference is always next instruction */ | 928 | pc++; /* reference is always next instruction */ |
| 929 | ci->u.l.savedpc = pc; /* save 'pc' */ | 929 | ci->u.l.savedpc = pc; /* save 'pc' */ |
| 930 | counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); | 930 | counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0); |
| 931 | if (counthook) | 931 | if (counthook) |
| 932 | resethookcount(L); /* reset count */ | 932 | resethookcount(L); /* reset count */ |
| 933 | else if (!(mask & LUA_MASKLINE)) | 933 | else if (!(mask & LUA_MASKLINE)) |
| 934 | return 1; /* no line hook and count != 0; nothing to be done now */ | 934 | return 1; /* no line hook and count != 0; nothing to be done now */ |
| 935 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ | 935 | if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */ |
| 936 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ | 936 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ |
| 937 | return 1; /* do not call hook again (VM yielded, so it did not move) */ | 937 | return 1; /* do not call hook again (VM yielded, so it did not move) */ |
| 938 | } | 938 | } |
| @@ -954,7 +954,6 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { | |||
| 954 | if (L->status == LUA_YIELD) { /* did hook yield? */ | 954 | if (L->status == LUA_YIELD) { /* did hook yield? */ |
| 955 | if (counthook) | 955 | if (counthook) |
| 956 | L->hookcount = 1; /* undo decrement to zero */ | 956 | L->hookcount = 1; /* undo decrement to zero */ |
| 957 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ | ||
| 958 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ | 957 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ |
| 959 | luaD_throw(L, LUA_YIELD); | 958 | luaD_throw(L, LUA_YIELD); |
| 960 | } | 959 | } |
| @@ -792,6 +792,10 @@ static void resume (lua_State *L, void *ud) { | |||
| 792 | lua_assert(L->status == LUA_YIELD); | 792 | lua_assert(L->status == LUA_YIELD); |
| 793 | L->status = LUA_OK; /* mark that it is running (again) */ | 793 | L->status = LUA_OK; /* mark that it is running (again) */ |
| 794 | if (isLua(ci)) { /* yielded inside a hook? */ | 794 | if (isLua(ci)) { /* yielded inside a hook? */ |
| 795 | /* undo increment made by 'luaG_traceexec': instruction was not | ||
| 796 | executed yet */ | ||
| 797 | lua_assert(ci->callstatus & CIST_HOOKYIELD); | ||
| 798 | ci->u.l.savedpc--; | ||
| 795 | L->top.p = firstArg; /* discard arguments */ | 799 | L->top.p = firstArg; /* discard arguments */ |
| 796 | luaV_execute(L, ci); /* just continue running Lua code */ | 800 | luaV_execute(L, ci); /* just continue running Lua code */ |
| 797 | } | 801 | } |
| @@ -241,7 +241,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
| 241 | return internshrstr(L, str, l); | 241 | return internshrstr(L, str, l); |
| 242 | else { | 242 | else { |
| 243 | TString *ts; | 243 | TString *ts; |
| 244 | if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char))) | 244 | if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString)))) |
| 245 | luaM_toobig(L); | 245 | luaM_toobig(L); |
| 246 | ts = luaS_createlngstrobj(L, l); | 246 | ts = luaS_createlngstrobj(L, l); |
| 247 | memcpy(getlngstr(ts), str, l * sizeof(char)); | 247 | memcpy(getlngstr(ts), str, l * sizeof(char)); |
| @@ -73,8 +73,9 @@ static void badexit (const char *fmt, const char *s1, const char *s2) { | |||
| 73 | 73 | ||
| 74 | 74 | ||
| 75 | static int tpanic (lua_State *L) { | 75 | static int tpanic (lua_State *L) { |
| 76 | const char *msg = lua_tostring(L, -1); | 76 | const char *msg = (lua_type(L, -1) == LUA_TSTRING) |
| 77 | if (msg == NULL) msg = "error object is not a string"; | 77 | ? lua_tostring(L, -1) |
| 78 | : "error object is not a string"; | ||
| 78 | return (badexit("PANIC: unprotected error in call to Lua API (%s)\n", | 79 | return (badexit("PANIC: unprotected error in call to Lua API (%s)\n", |
| 79 | msg, NULL), | 80 | msg, NULL), |
| 80 | 0); /* do not return to Lua */ | 81 | 0); /* do not return to Lua */ |
| @@ -655,7 +655,7 @@ void luaV_concat (lua_State *L, int total) { | |||
| 655 | /* collect total length and number of strings */ | 655 | /* collect total length and number of strings */ |
| 656 | for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { | 656 | for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { |
| 657 | size_t l = tsslen(tsvalue(s2v(top - n - 1))); | 657 | size_t l = tsslen(tsvalue(s2v(top - n - 1))); |
| 658 | if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { | 658 | if (l_unlikely(l >= MAX_SIZE - sizeof(TString) - tl)) { |
| 659 | L->top.p = top - total; /* pop strings to avoid wasting stack */ | 659 | L->top.p = top - total; /* pop strings to avoid wasting stack */ |
| 660 | luaG_runerror(L, "string length overflow"); | 660 | luaG_runerror(L, "string length overflow"); |
| 661 | } | 661 | } |
diff --git a/manual/manual.of b/manual/manual.of index 42269ff4..e3cbddb3 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -4552,6 +4552,10 @@ The pointer returned by @id{lua_tolstring} | |||
| 4552 | may be invalidated by the garbage collector if the | 4552 | may be invalidated by the garbage collector if the |
| 4553 | corresponding Lua value is removed from the stack @see{constchar}. | 4553 | corresponding Lua value is removed from the stack @see{constchar}. |
| 4554 | 4554 | ||
| 4555 | This function can raise memory errors only | ||
| 4556 | when converting a number to a string | ||
| 4557 | (as then it may have to create a new string). | ||
| 4558 | |||
| 4555 | } | 4559 | } |
| 4556 | 4560 | ||
| 4557 | @APIEntry{lua_Number lua_tonumber (lua_State *L, int index);| | 4561 | @APIEntry{lua_Number lua_tonumber (lua_State *L, int index);| |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 6c15db03..664ef5fa 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
| @@ -610,18 +610,20 @@ else | |||
| 610 | -- (bug in 5.2/5.3) | 610 | -- (bug in 5.2/5.3) |
| 611 | c = coroutine.create(function (a, ...) | 611 | c = coroutine.create(function (a, ...) |
| 612 | T.sethook("yield 0", "l") -- will yield on next two lines | 612 | T.sethook("yield 0", "l") -- will yield on next two lines |
| 613 | assert(a == 10) | 613 | local b = a |
| 614 | return ... | 614 | return ... |
| 615 | end) | 615 | end) |
| 616 | 616 | ||
| 617 | assert(coroutine.resume(c, 1, 2, 3)) -- start coroutine | 617 | assert(coroutine.resume(c, 1, 2, 3)) -- start coroutine |
| 618 | local n,v = debug.getlocal(c, 0, 1) -- check its local | 618 | local n,v = debug.getlocal(c, 0, 1) -- check its local |
| 619 | assert(n == "a" and v == 1) | 619 | assert(n == "a" and v == 1 and debug.getlocal(c, 0, 2) ~= "b") |
| 620 | assert(debug.setlocal(c, 0, 1, 10)) -- test 'setlocal' | 620 | assert(debug.setlocal(c, 0, 1, 10)) -- test 'setlocal' |
| 621 | local t = debug.getinfo(c, 0) -- test 'getinfo' | 621 | local t = debug.getinfo(c, 0) -- test 'getinfo' |
| 622 | assert(t.currentline == t.linedefined + 1) | 622 | assert(t.currentline == t.linedefined + 2) |
| 623 | assert(not debug.getinfo(c, 1)) -- no other level | 623 | assert(not debug.getinfo(c, 1)) -- no other level |
| 624 | assert(coroutine.resume(c)) -- run next line | 624 | assert(coroutine.resume(c)) -- run next line |
| 625 | local n,v = debug.getlocal(c, 0, 2) -- check next local | ||
| 626 | assert(n == "b" and v == 10) | ||
| 625 | v = {coroutine.resume(c)} -- finish coroutine | 627 | v = {coroutine.resume(c)} -- finish coroutine |
| 626 | assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef) | 628 | assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef) |
| 627 | assert(not coroutine.resume(c)) | 629 | assert(not coroutine.resume(c)) |
