Fixed bug in 'lua_upvaluejoin'

Bug-fix: joining an upvalue with itself could cause a use-after-free
crash.
This commit is contained in:
Roberto Ierusalimschy 2019-03-27 14:30:12 -03:00
parent f059c2bcc8
commit 89aee84cbc
3 changed files with 41 additions and 39 deletions

64
bugs
View File

@ -357,7 +357,7 @@ co = coroutine.create(co_func)
coroutine.resume(co) coroutine.resume(co)
coroutine.resume(co) --> seg. fault coroutine.resume(co) --> seg. fault
]], ]],
report = [[by Alex Bilyk, 09/05/2003]], report = [[by Alex Bilyk, 09/05/2003]],
patch = [[ patch = [[
* ldo.c: * ldo.c:
325,326c325 325,326c325
@ -399,7 +399,7 @@ what = [[file:close cannot be called without a file. (results in seg fault)]],
example = [[ example = [[
> io.stdin.close() -- correct call shold be io.stdin:close() > io.stdin.close() -- correct call shold be io.stdin:close()
]], ]],
report = [[by Tuomo Valkonen, 27/05/2003]], report = [[by Tuomo Valkonen, 27/05/2003]],
patch = [[ patch = [[
* liolib.c: * liolib.c:
161c161 161c161
@ -1641,7 +1641,7 @@ what = [[debug.sethook/gethook may overflow the thread's stack]],
report = [[Ivko Stanilov, on 2008/01/04]], report = [[Ivko Stanilov, on 2008/01/04]],
since = [[5.1]], since = [[5.1]],
example = [[ example = [[
a = coroutine.create(function() yield() end) a = coroutine.create(function() yield() end)
coroutine.resume(a) coroutine.resume(a)
debug.sethook(a) -- may overflow the stack of 'a' debug.sethook(a) -- may overflow the stack of 'a'
]], ]],
@ -2707,7 +2707,7 @@ local firsttime = true
local function foo () local function foo ()
if firsttime then if firsttime then
firsttime = false firsttime = false
return "a = 1" return "a = 1"
else else
for i = 1, 10 do for i = 1, 10 do
print(debug.getlocal(2, i)) print(debug.getlocal(2, i))
@ -2899,28 +2899,6 @@ patch = [[
]] ]]
} }
Bug{
what = [[Lua does not check memory use when creating error messages]],
report = [[John Dunn, 2012/09/24]],
since = [[5.2.0]],
fix = nil,
example = [[
local code = "function test()\n bob.joe.larry = 23\n end"
load(code)()
-- memory will grow steadly
for i = 1, math.huge do
pcall(test)
if i % 100000 == 0 then
io.write(collectgarbage'count'*1024, "\n")
end
end
]],
patch = [[
]]
}
@ -3859,11 +3837,11 @@ report = [[Viacheslav Usov, 2017/07/06]],
since = [[5.3.2]], since = [[5.3.2]],
fix = nil, fix = nil,
example = [[ example = [[
function test() function test()
bob.joe.larry = 23 bob.joe.larry = 23
end end
-- memory will grow steadly -- memory will grow steadly
for i = 1, math.huge do for i = 1, math.huge do
pcall(test) pcall(test)
if i % 100000 == 0 then if i % 100000 == 0 then
@ -3892,7 +3870,7 @@ report = [[云风 Cloud Wu, 2017/08/15]],
since = [[5.2]], since = [[5.2]],
fix = nil, fix = nil,
example = [[ example = [[
-- The following chunk, under a memory checker like valgrind, -- The following chunk, under a memory checker like valgrind,
-- produces a memory access violation. -- produces a memory access violation.
local a = setmetatable({}, {__mode = 'kv'}) local a = setmetatable({}, {__mode = 'kv'})
@ -4020,7 +3998,6 @@ patch = [[
----------------------------------------------------------------- -----------------------------------------------------------------
-- Lua 5.3.5 -- Lua 5.3.5
--[=[
Bug{ Bug{
what = [[Long brackets with a huge number of '=' overflow some what = [[Long brackets with a huge number of '=' overflow some
internal buffer arithmetic]], internal buffer arithmetic]],
@ -4111,9 +4088,34 @@ patch = [[
} }
]] ]]
} }
]=]
Bug{
what = [[joining an upvalue with itself can cause a use-after-free crash]],
report = [[Fady Othman, 2019/01/10]],
since = [[5.3]],
fix = nil,
example = [[
-- the next code may crash the machine
f=load(function() end)
interesting={}
interesting[0]=string.rep("A",512)
debug.upvaluejoin(f,1,f,1)
]],
patch = [[
--- a/lapi.c
+++ b/lapi.c
@@ -1289,6 +1289,8 @@ 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);
+ if (*up1 == *up2)
+ return;
luaC_upvdeccount(L, *up1);
*up1 = *up2;
(*up1)->refcount++;
]]
}
--[=[ --[=[

12
lapi.c
View File

@ -1254,13 +1254,12 @@ 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 UpVal **getupvalref (lua_State *L, int fidx, int n) {
LClosure *f; LClosure *f;
StkId fi = index2addr(L, fidx); StkId fi = index2addr(L, fidx);
api_check(L, ttisLclosure(fi), "Lua function expected"); api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi); f = clLvalue(fi);
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); 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 */ return &f->upvals[n - 1]; /* get its upvalue pointer */
} }
@ -1269,7 +1268,7 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
StkId fi = index2addr(L, fidx); StkId fi = index2addr(L, fidx);
switch (ttype(fi)) { switch (ttype(fi)) {
case LUA_TLCL: { /* lua closure */ case LUA_TLCL: { /* lua closure */
return *getupvalref(L, fidx, n, NULL); return *getupvalref(L, fidx, n);
} }
case LUA_TCCL: { /* C closure */ case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi); CClosure *f = clCvalue(fi);
@ -1286,9 +1285,10 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
int fidx2, int n2) { int fidx2, int n2) {
LClosure *f1; UpVal **up1 = getupvalref(L, fidx1, n1);
UpVal **up1 = getupvalref(L, fidx1, n1, &f1); UpVal **up2 = getupvalref(L, fidx2, n2);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL); if (*up1 == *up2)
return;
luaC_upvdeccount(L, *up1); luaC_upvdeccount(L, *up1);
*up1 = *up2; *up1 = *up2;
(*up1)->refcount++; (*up1)->refcount++;

View File

@ -58,9 +58,9 @@ MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS= -ldl -lreadline MYLIBS= -ldl -lreadline
CC= clang-3.8 CC= gcc
CFLAGS= -Wall -O2 $(MYCFLAGS) CFLAGS= -Wall -O2 $(MYCFLAGS)
AR= ar rcu AR= ar rc
RANLIB= ranlib RANLIB= ranlib
RM= rm -f RM= rm -f