b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 89aee84cbc9224f638f3b7951b306d2ee8ecb71e Mon Sep 17 00:00:00 2001 |
| 2 | From: Roberto Ierusalimschy <roberto@inf.puc-rio.br> |
| 3 | Date: Wed, 27 Mar 2019 14:30:12 -0300 |
| 4 | Subject: [PATCH] Fixed bug in 'lua_upvaluejoin' |
| 5 | |
| 6 | Bug-fix: joining an upvalue with itself could cause a use-after-free |
| 7 | crash. |
| 8 | --- |
| 9 | src/lapi.c | 12 +++++------ |
| 10 | 1 file changed, 41 insertions(+), 39 deletions(-) |
| 11 | |
| 12 | --- a/src/lapi.c |
| 13 | +++ b/src/lapi.c |
| 14 | @@ -1254,13 +1254,12 @@ LUA_API const char *lua_setupvalue (lua_ |
| 15 | } |
| 16 | |
| 17 | |
| 18 | -static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { |
| 19 | +static UpVal **getupvalref (lua_State *L, int fidx, int n) { |
| 20 | LClosure *f; |
| 21 | StkId fi = index2addr(L, fidx); |
| 22 | api_check(L, ttisLclosure(fi), "Lua function expected"); |
| 23 | f = clLvalue(fi); |
| 24 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); |
| 25 | - if (pf) *pf = f; |
| 26 | return &f->upvals[n - 1]; /* get its upvalue pointer */ |
| 27 | } |
| 28 | |
| 29 | @@ -1269,7 +1268,7 @@ LUA_API void *lua_upvalueid (lua_State * |
| 30 | StkId fi = index2addr(L, fidx); |
| 31 | switch (ttype(fi)) { |
| 32 | case LUA_TLCL: { /* lua closure */ |
| 33 | - return *getupvalref(L, fidx, n, NULL); |
| 34 | + return *getupvalref(L, fidx, n); |
| 35 | } |
| 36 | case LUA_TCCL: { /* C closure */ |
| 37 | CClosure *f = clCvalue(fi); |
| 38 | @@ -1286,9 +1285,10 @@ LUA_API void *lua_upvalueid (lua_State * |
| 39 | |
| 40 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, |
| 41 | int fidx2, int n2) { |
| 42 | - LClosure *f1; |
| 43 | - UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
| 44 | - UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
| 45 | + UpVal **up1 = getupvalref(L, fidx1, n1); |
| 46 | + UpVal **up2 = getupvalref(L, fidx2, n2); |
| 47 | + if (*up1 == *up2) |
| 48 | + return; |
| 49 | luaC_upvdeccount(L, *up1); |
| 50 | *up1 = *up2; |
| 51 | (*up1)->refcount++; |