Avoid setting the stack top below upvalues to be closed

When leaving a scope, the new stack top should be set only after
closing any upvalue, to avoid manipulating values in an "invalid"
part of the stack.
diff --git a/lapi.c b/lapi.c
index 661fdb1..0f81107 100644
--- a/lapi.c
+++ b/lapi.c
@@ -171,19 +171,20 @@
 
 LUA_API void lua_settop (lua_State *L, int idx) {
   StkId func = L->ci->func;
+  int diff;  /* difference for new top */
   lua_lock(L);
   if (idx >= 0) {
-    StkId newtop = (func + 1) + idx;
-    api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
-    while (L->top < newtop)
-      setnilvalue(s2v(L->top++));
-    L->top = newtop;
+    api_check(L, idx <= L->ci->top - (func + 1), "new top too large");
+    diff = (func + 1) + idx - L->top;
+    for (; diff > 0; diff--)
+      setnilvalue(s2v(L->top++));  /* clear new slots */
   }
   else {
     api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
-    L->top += idx+1;  /* 'subtract' index (index is negative) */
+    diff = idx + 1;  /* will "subtract" index (as it is negative) */
   }
-  luaF_close(L, L->top, LUA_OK);
+  luaF_close(L, L->top + diff, LUA_OK);
+  L->top += diff;  /* correct top only after closing any upvalue */
   lua_unlock(L);
 }
 
diff --git a/lfunc.c b/lfunc.c
index 5511499..68d0632 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -202,6 +202,7 @@
   while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
     StkId upl = uplevel(uv);
     TValue *slot = &uv->u.value;  /* new position for value */
+    lua_assert(upl < L->top);
     luaF_unlinkupval(uv);
     setobj(L, slot, uv->v);  /* move value to upvalue slot */
     uv->v = slot;  /* now current value lives here */
diff --git a/lvm.c b/lvm.c
index d365bcd..9838500 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1601,15 +1601,17 @@
         int n = GETARG_B(i) - 1;  /* number of results */
         if (n < 0)  /* not fixed? */
           n = cast_int(L->top - ra);  /* get what is available */
-        else
-          L->top = ra + n;  /* set call for 'luaD_poscall' */
         savepc(ci);
         if (TESTARG_k(i)) {
           int nparams1 = GETARG_C(i);
+          if (L->top < ci->top)
+            L->top = ci->top;
           luaF_close(L, base, LUA_OK);  /* there may be open upvalues */
+          updatestack(ci);
           if (nparams1)  /* vararg function? */
             ci->func -= ci->u.l.nextraargs + nparams1;
         }
+        L->top = ra + n;  /* set call for 'luaD_poscall' */
         luaD_poscall(L, ci, n);
         return;
       }