diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-13 15:30:52 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-13 15:30:52 -0300 |
| commit | 22974326ca0d4f893849ce722cc1d65b3e228f42 (patch) | |
| tree | 1b4cb2cad1c55edce63e9fe6e468b1833950397d | |
| parent | c931d86e98da320c71da70c16d44aa28e9755520 (diff) | |
| download | lua-22974326ca0d4f893849ce722cc1d65b3e228f42.tar.gz lua-22974326ca0d4f893849ce722cc1d65b3e228f42.tar.bz2 lua-22974326ca0d4f893849ce722cc1d65b3e228f42.zip | |
Use after free in 'luaV_finishset'
If a metatable is a weak table, its __newindex field could be collected
by an emergency collection while being used in 'luaV_finishset'. (This
bug has similarities with bug 5.3.2-1, fixed in commit a272fa66.)
| -rw-r--r-- | lapi.c | 5 | ||||
| -rw-r--r-- | lvm.c | 8 | ||||
| -rw-r--r-- | testes/events.lua | 13 |
3 files changed, 25 insertions, 1 deletions
| @@ -681,6 +681,11 @@ static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | |||
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | 683 | ||
| 684 | /* | ||
| 685 | ** The following function assumes that the registry cannot be a weak | ||
| 686 | ** table, so that en mergency collection while using the global table | ||
| 687 | ** cannot collect it. | ||
| 688 | */ | ||
| 684 | static void getGlobalTable (lua_State *L, TValue *gt) { | 689 | static void getGlobalTable (lua_State *L, TValue *gt) { |
| 685 | Table *registry = hvalue(&G(L)->l_registry); | 690 | Table *registry = hvalue(&G(L)->l_registry); |
| 686 | lu_byte tag = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); | 691 | lu_byte tag = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); |
| @@ -325,6 +325,11 @@ lu_byte luaV_finishget (lua_State *L, const TValue *t, TValue *key, | |||
| 325 | 325 | ||
| 326 | /* | 326 | /* |
| 327 | ** Finish a table assignment 't[key] = val'. | 327 | ** Finish a table assignment 't[key] = val'. |
| 328 | ** About anchoring the table before the call to 'luaH_finishset': | ||
| 329 | ** This call may trigger an emergency collection. When loop>0, | ||
| 330 | ** the table being acessed is a field in some metatable. If this | ||
| 331 | ** metatable is weak and the table is not anchored, this collection | ||
| 332 | ** could collect that table while it is being updated. | ||
| 328 | */ | 333 | */ |
| 329 | void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 334 | void luaV_finishset (lua_State *L, const TValue *t, TValue *key, |
| 330 | TValue *val, int hres) { | 335 | TValue *val, int hres) { |
| @@ -335,7 +340,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
| 335 | Table *h = hvalue(t); /* save 't' table */ | 340 | Table *h = hvalue(t); /* save 't' table */ |
| 336 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ | 341 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ |
| 337 | if (tm == NULL) { /* no metamethod? */ | 342 | if (tm == NULL) { /* no metamethod? */ |
| 343 | sethvalue2s(L, L->top.p, h); /* anchor 't' */ | ||
| 344 | L->top.p++; /* assume EXTRA_STACK */ | ||
| 338 | luaH_finishset(L, h, key, val, hres); /* set new value */ | 345 | luaH_finishset(L, h, key, val, hres); /* set new value */ |
| 346 | L->top.p--; | ||
| 339 | invalidateTMcache(h); | 347 | invalidateTMcache(h); |
| 340 | luaC_barrierback(L, obj2gco(h), val); | 348 | luaC_barrierback(L, obj2gco(h), val); |
| 341 | return; | 349 | return; |
diff --git a/testes/events.lua b/testes/events.lua index 2500fbd5..7e434b1f 100644 --- a/testes/events.lua +++ b/testes/events.lua | |||
| @@ -379,6 +379,17 @@ x = 0 .."a".."b"..c..d.."e".."f".."g" | |||
| 379 | assert(x.val == "0abcdefg") | 379 | assert(x.val == "0abcdefg") |
| 380 | 380 | ||
| 381 | 381 | ||
| 382 | do | ||
| 383 | -- bug since 5.4.1 (test needs T) | ||
| 384 | local mt = setmetatable({__newindex={}}, {__mode='v'}) | ||
| 385 | local t = setmetatable({}, mt) | ||
| 386 | |||
| 387 | if T then T.allocfailnext() end | ||
| 388 | |||
| 389 | -- seg. fault | ||
| 390 | for i=1, 10 do t[i] = 1 end | ||
| 391 | end | ||
| 392 | |||
| 382 | -- concat metamethod x numbers (bug in 5.1.1) | 393 | -- concat metamethod x numbers (bug in 5.1.1) |
| 383 | c = {} | 394 | c = {} |
| 384 | local x | 395 | local x |
| @@ -481,7 +492,7 @@ assert(not pcall(function (a,b) return a[b] end, a, 10)) | |||
| 481 | assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true)) | 492 | assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true)) |
| 482 | 493 | ||
| 483 | -- bug in 5.1 | 494 | -- bug in 5.1 |
| 484 | T, K, V = nil | 495 | local T, K, V = nil |
| 485 | grandparent = {} | 496 | grandparent = {} |
| 486 | grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end | 497 | grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end |
| 487 | 498 | ||
