'lua_upvalueid' returns NULL on invalid upvalue index
diff --git a/.gitignore b/.gitignore
index 735661e..ae2899e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,6 @@
testes/time-debug.txt
testes/libs/all
+
+temp
+lua
diff --git a/lapi.c b/lapi.c
index 9048245..c824da2 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1383,13 +1383,16 @@
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
+ static const UpVal *const nullup = NULL;
LClosure *f;
TValue *fi = index2value(L, fidx);
api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi);
- api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
if (pf) *pf = f;
- return &f->upvals[n - 1]; /* get its upvalue pointer */
+ if (1 <= n && n <= f->p->sizeupvalues)
+ return &f->upvals[n - 1]; /* get its upvalue pointer */
+ else
+ return (UpVal**)&nullup;
}
@@ -1401,11 +1404,14 @@
}
case LUA_VCCL: { /* C closure */
CClosure *f = clCvalue(fi);
- api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
- return &f->upvalue[n - 1];
- }
+ if (1 <= n && n <= f->nupvalues)
+ return &f->upvalue[n - 1];
+ /* else */
+ } /* FALLTHROUGH */
+ case LUA_VLCF:
+ return NULL; /* light C functions have no upvalues */
default: {
- api_check(L, 0, "closure expected");
+ api_check(L, 0, "function expected");
return NULL;
}
}
@@ -1417,6 +1423,7 @@
LClosure *f1;
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
+ api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index");
*up1 = *up2;
luaC_objbarrier(L, f1, *up1);
}
diff --git a/ldblib.c b/ldblib.c
index 26058b5..5a326ad 100644
--- a/ldblib.c
+++ b/ldblib.c
@@ -281,25 +281,33 @@
** Check whether a given upvalue from a given closure exists and
** returns its index
*/
-static int checkupval (lua_State *L, int argf, int argnup) {
+static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
+ void *id;
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
- luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
- "invalid upvalue index");
- return nup;
+ id = lua_upvalueid(L, argf, nup);
+ if (pnup) {
+ luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
+ *pnup = nup;
+ }
+ return id;
}
static int db_upvalueid (lua_State *L) {
- int n = checkupval(L, 1, 2);
- lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
+ void *id = checkupval(L, 1, 2, NULL);
+ if (id != NULL)
+ lua_pushlightuserdata(L, id);
+ else
+ luaL_pushfail(L);
return 1;
}
static int db_upvaluejoin (lua_State *L) {
- int n1 = checkupval(L, 1, 2);
- int n2 = checkupval(L, 3, 4);
+ int n1, n2;
+ checkupval(L, 1, 2, &n1);
+ checkupval(L, 3, 4, &n2);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
diff --git a/testes/closure.lua b/testes/closure.lua
index cdeaeba..c245367 100644
--- a/testes/closure.lua
+++ b/testes/closure.lua
@@ -242,7 +242,7 @@
assert(debug.upvalueid(foo1, 1))
assert(debug.upvalueid(foo1, 2))
-assert(not pcall(debug.upvalueid, foo1, 3))
+assert(not debug.upvalueid(foo1, 3))
assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
assert(debug.upvalueid(foo3, 1))