diff --git a/VM/src/lapi.cpp b/VM/src/lapi.cpp index d2091c6..1528aa3 100644 --- a/VM/src/lapi.cpp +++ b/VM/src/lapi.cpp @@ -1285,10 +1285,12 @@ static const char* aux_upvalue(StkId fi, int n, TValue** val) else { Proto* p = f->l.p; - if (!(1 <= n && n <= p->sizeupvalues)) + if (!(1 <= n && n <= p->nups)) // not a valid upvalue return NULL; TValue* r = &f->l.uprefs[n - 1]; *val = ttisupval(r) ? upvalue(r)->v : r; + if (!(1 <= n && n <= p->sizeupvalues)) // don't have a name for this upvalue + return ""; return getstr(p->upvalues[n - 1]); } } diff --git a/tests/Conformance.test.cpp b/tests/Conformance.test.cpp index d7340ce..13600cb 100644 --- a/tests/Conformance.test.cpp +++ b/tests/Conformance.test.cpp @@ -693,6 +693,34 @@ TEST_CASE("Debugger") CHECK(stephits > 100); // note; this will depend on number of instructions which can vary, so we just make sure the callback gets hit often } +TEST_CASE("NDebugGetUpValue") +{ + lua_CompileOptions copts = defaultOptions(); + copts.debugLevel = 0; + // Don't optimize away any upvalues + copts.optimizationLevel = 0; + + runConformance( + "ndebug_upvalues.lua", + nullptr, + [](lua_State* L) { + lua_checkstack(L, LUA_MINSTACK); + + // push the second frame's closure to the stack + lua_Debug ar = {}; + REQUIRE(lua_getinfo(L, 1, "f", &ar)); + + // get the first upvalue + const char* u = lua_getupvalue(L, -1, 1); + REQUIRE(u); + // upvalue name is unknown without debug info + CHECK(strcmp(u, "") == 0); + CHECK(lua_tointeger(L, -1) == 5); + lua_pop(L, 2); + }, + nullptr, &copts, /* skipCodegen */ false); +} + TEST_CASE("SameHash") { extern unsigned int luaS_hash(const char* str, size_t len); // internal function, declared in lstring.h - not exposed via lua.h diff --git a/tests/conformance/ndebug_upvalues.lua b/tests/conformance/ndebug_upvalues.lua new file mode 100644 index 0000000..bdb67f2 --- /dev/null +++ b/tests/conformance/ndebug_upvalues.lua @@ -0,0 +1,13 @@ +-- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details +-- This tests that the lua_*upval() APIs work correctly even with debug info disabled +local foo = 5 +function clo_test() + -- so `foo` gets captured as an upval + print(foo) + -- yield so we can look at clo_test's upvalues + coroutine.yield() +end + +clo_test() + +return 'OK'