From 30528049f1d11ea2854a6431e8e8524f83206559 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 12 Oct 2020 14:51:28 -0300 Subject: [PATCH] 'lua_upvalueid' returns NULL on invalid upvalue index --- .gitignore | 3 +++ lapi.c | 19 +++++++++++++------ ldblib.c | 24 ++++++++++++++++-------- testes/closure.lua | 2 +- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 735661ea..ae2899e0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ testes/time.txt testes/time-debug.txt testes/libs/all + +temp +lua diff --git a/lapi.c b/lapi.c index 9048245f..c824da27 100644 --- a/lapi.c +++ b/lapi.c @@ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { 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 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { } 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 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, 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 26058b50..5a326ade 100644 --- a/ldblib.c +++ b/ldblib.c @@ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) { ** 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 cdeaebaa..c2453677 100644 --- a/testes/closure.lua +++ b/testes/closure.lua @@ -242,7 +242,7 @@ end 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))