diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-12 14:51:28 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-12 14:51:28 -0300 |
commit | 30528049f1d11ea2854a6431e8e8524f83206559 (patch) | |
tree | f50e46758cb5673df7e6e456b1e94812a2c5050d | |
parent | 9a89fb1c9dfeda4640780111f9e9437f08cfad88 (diff) | |
download | lua-30528049f1d11ea2854a6431e8e8524f83206559.tar.gz lua-30528049f1d11ea2854a6431e8e8524f83206559.tar.bz2 lua-30528049f1d11ea2854a6431e8e8524f83206559.zip |
'lua_upvalueid' returns NULL on invalid upvalue index
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | lapi.c | 19 | ||||
-rw-r--r-- | ldblib.c | 24 | ||||
-rw-r--r-- | testes/closure.lua | 2 |
4 files changed, 33 insertions, 15 deletions
@@ -10,3 +10,6 @@ testes/time.txt | |||
10 | testes/time-debug.txt | 10 | testes/time-debug.txt |
11 | 11 | ||
12 | testes/libs/all | 12 | testes/libs/all |
13 | |||
14 | temp | ||
15 | lua | ||
@@ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |||
1383 | 1383 | ||
1384 | 1384 | ||
1385 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { | 1385 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { |
1386 | static const UpVal *const nullup = NULL; | ||
1386 | LClosure *f; | 1387 | LClosure *f; |
1387 | TValue *fi = index2value(L, fidx); | 1388 | TValue *fi = index2value(L, fidx); |
1388 | api_check(L, ttisLclosure(fi), "Lua function expected"); | 1389 | api_check(L, ttisLclosure(fi), "Lua function expected"); |
1389 | f = clLvalue(fi); | 1390 | f = clLvalue(fi); |
1390 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); | ||
1391 | if (pf) *pf = f; | 1391 | if (pf) *pf = f; |
1392 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | 1392 | if (1 <= n && n <= f->p->sizeupvalues) |
1393 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | ||
1394 | else | ||
1395 | return (UpVal**)&nullup; | ||
1393 | } | 1396 | } |
1394 | 1397 | ||
1395 | 1398 | ||
@@ -1401,11 +1404,14 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | |||
1401 | } | 1404 | } |
1402 | case LUA_VCCL: { /* C closure */ | 1405 | case LUA_VCCL: { /* C closure */ |
1403 | CClosure *f = clCvalue(fi); | 1406 | CClosure *f = clCvalue(fi); |
1404 | api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); | 1407 | if (1 <= n && n <= f->nupvalues) |
1405 | return &f->upvalue[n - 1]; | 1408 | return &f->upvalue[n - 1]; |
1406 | } | 1409 | /* else */ |
1410 | } /* FALLTHROUGH */ | ||
1411 | case LUA_VLCF: | ||
1412 | return NULL; /* light C functions have no upvalues */ | ||
1407 | default: { | 1413 | default: { |
1408 | api_check(L, 0, "closure expected"); | 1414 | api_check(L, 0, "function expected"); |
1409 | return NULL; | 1415 | return NULL; |
1410 | } | 1416 | } |
1411 | } | 1417 | } |
@@ -1417,6 +1423,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | |||
1417 | LClosure *f1; | 1423 | LClosure *f1; |
1418 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | 1424 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
1419 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | 1425 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
1426 | api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); | ||
1420 | *up1 = *up2; | 1427 | *up1 = *up2; |
1421 | luaC_objbarrier(L, f1, *up1); | 1428 | luaC_objbarrier(L, f1, *up1); |
1422 | } | 1429 | } |
@@ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) { | |||
281 | ** Check whether a given upvalue from a given closure exists and | 281 | ** Check whether a given upvalue from a given closure exists and |
282 | ** returns its index | 282 | ** returns its index |
283 | */ | 283 | */ |
284 | static int checkupval (lua_State *L, int argf, int argnup) { | 284 | static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { |
285 | void *id; | ||
285 | int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ | 286 | int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ |
286 | luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ | 287 | luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ |
287 | luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, | 288 | id = lua_upvalueid(L, argf, nup); |
288 | "invalid upvalue index"); | 289 | if (pnup) { |
289 | return nup; | 290 | luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); |
291 | *pnup = nup; | ||
292 | } | ||
293 | return id; | ||
290 | } | 294 | } |
291 | 295 | ||
292 | 296 | ||
293 | static int db_upvalueid (lua_State *L) { | 297 | static int db_upvalueid (lua_State *L) { |
294 | int n = checkupval(L, 1, 2); | 298 | void *id = checkupval(L, 1, 2, NULL); |
295 | lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); | 299 | if (id != NULL) |
300 | lua_pushlightuserdata(L, id); | ||
301 | else | ||
302 | luaL_pushfail(L); | ||
296 | return 1; | 303 | return 1; |
297 | } | 304 | } |
298 | 305 | ||
299 | 306 | ||
300 | static int db_upvaluejoin (lua_State *L) { | 307 | static int db_upvaluejoin (lua_State *L) { |
301 | int n1 = checkupval(L, 1, 2); | 308 | int n1, n2; |
302 | int n2 = checkupval(L, 3, 4); | 309 | checkupval(L, 1, 2, &n1); |
310 | checkupval(L, 3, 4, &n2); | ||
303 | luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); | 311 | luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); |
304 | luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); | 312 | luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); |
305 | lua_upvaluejoin(L, 1, n1, 3, n2); | 313 | 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 | |||
242 | 242 | ||
243 | assert(debug.upvalueid(foo1, 1)) | 243 | assert(debug.upvalueid(foo1, 1)) |
244 | assert(debug.upvalueid(foo1, 2)) | 244 | assert(debug.upvalueid(foo1, 2)) |
245 | assert(not pcall(debug.upvalueid, foo1, 3)) | 245 | assert(not debug.upvalueid(foo1, 3)) |
246 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) | 246 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) |
247 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) | 247 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) |
248 | assert(debug.upvalueid(foo3, 1)) | 248 | assert(debug.upvalueid(foo3, 1)) |