diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-27 14:30:12 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-27 14:30:12 -0300 |
| commit | 89aee84cbc9224f638f3b7951b306d2ee8ecb71e (patch) | |
| tree | 12e1664dbc5a7a5b519c9971dbb0ec31289201e0 | |
| parent | f059c2bcc8e0c99287657f953cca9ba730a5432a (diff) | |
| download | lua-89aee84cbc9224f638f3b7951b306d2ee8ecb71e.tar.gz lua-89aee84cbc9224f638f3b7951b306d2ee8ecb71e.tar.bz2 lua-89aee84cbc9224f638f3b7951b306d2ee8ecb71e.zip | |
Fixed bug in 'lua_upvaluejoin'
Bug-fix: joining an upvalue with itself could cause a use-after-free
crash.
| -rw-r--r-- | bugs | 64 | ||||
| -rw-r--r-- | lapi.c | 12 | ||||
| -rw-r--r-- | makefile | 4 |
3 files changed, 41 insertions, 39 deletions
| @@ -357,7 +357,7 @@ co = coroutine.create(co_func) | |||
| 357 | coroutine.resume(co) | 357 | coroutine.resume(co) |
| 358 | coroutine.resume(co) --> seg. fault | 358 | coroutine.resume(co) --> seg. fault |
| 359 | ]], | 359 | ]], |
| 360 | report = [[by Alex Bilyk, 09/05/2003]], | 360 | report = [[by Alex Bilyk, 09/05/2003]], |
| 361 | patch = [[ | 361 | patch = [[ |
| 362 | * ldo.c: | 362 | * ldo.c: |
| 363 | 325,326c325 | 363 | 325,326c325 |
| @@ -399,7 +399,7 @@ what = [[file:close cannot be called without a file. (results in seg fault)]], | |||
| 399 | example = [[ | 399 | example = [[ |
| 400 | > io.stdin.close() -- correct call shold be io.stdin:close() | 400 | > io.stdin.close() -- correct call shold be io.stdin:close() |
| 401 | ]], | 401 | ]], |
| 402 | report = [[by Tuomo Valkonen, 27/05/2003]], | 402 | report = [[by Tuomo Valkonen, 27/05/2003]], |
| 403 | patch = [[ | 403 | patch = [[ |
| 404 | * liolib.c: | 404 | * liolib.c: |
| 405 | 161c161 | 405 | 161c161 |
| @@ -1641,7 +1641,7 @@ what = [[debug.sethook/gethook may overflow the thread's stack]], | |||
| 1641 | report = [[Ivko Stanilov, on 2008/01/04]], | 1641 | report = [[Ivko Stanilov, on 2008/01/04]], |
| 1642 | since = [[5.1]], | 1642 | since = [[5.1]], |
| 1643 | example = [[ | 1643 | example = [[ |
| 1644 | a = coroutine.create(function() yield() end) | 1644 | a = coroutine.create(function() yield() end) |
| 1645 | coroutine.resume(a) | 1645 | coroutine.resume(a) |
| 1646 | debug.sethook(a) -- may overflow the stack of 'a' | 1646 | debug.sethook(a) -- may overflow the stack of 'a' |
| 1647 | ]], | 1647 | ]], |
| @@ -2707,7 +2707,7 @@ local firsttime = true | |||
| 2707 | local function foo () | 2707 | local function foo () |
| 2708 | if firsttime then | 2708 | if firsttime then |
| 2709 | firsttime = false | 2709 | firsttime = false |
| 2710 | return "a = 1" | 2710 | return "a = 1" |
| 2711 | else | 2711 | else |
| 2712 | for i = 1, 10 do | 2712 | for i = 1, 10 do |
| 2713 | print(debug.getlocal(2, i)) | 2713 | print(debug.getlocal(2, i)) |
| @@ -2899,28 +2899,6 @@ patch = [[ | |||
| 2899 | ]] | 2899 | ]] |
| 2900 | } | 2900 | } |
| 2901 | 2901 | ||
| 2902 | Bug{ | ||
| 2903 | what = [[Lua does not check memory use when creating error messages]], | ||
| 2904 | report = [[John Dunn, 2012/09/24]], | ||
| 2905 | since = [[5.2.0]], | ||
| 2906 | fix = nil, | ||
| 2907 | example = [[ | ||
| 2908 | local code = "function test()\n bob.joe.larry = 23\n end" | ||
| 2909 | |||
| 2910 | load(code)() | ||
| 2911 | |||
| 2912 | -- memory will grow steadly | ||
| 2913 | for i = 1, math.huge do | ||
| 2914 | pcall(test) | ||
| 2915 | if i % 100000 == 0 then | ||
| 2916 | io.write(collectgarbage'count'*1024, "\n") | ||
| 2917 | end | ||
| 2918 | end | ||
| 2919 | ]], | ||
| 2920 | patch = [[ | ||
| 2921 | ]] | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | 2902 | ||
| 2925 | 2903 | ||
| 2926 | 2904 | ||
| @@ -3859,11 +3837,11 @@ report = [[Viacheslav Usov, 2017/07/06]], | |||
| 3859 | since = [[5.3.2]], | 3837 | since = [[5.3.2]], |
| 3860 | fix = nil, | 3838 | fix = nil, |
| 3861 | example = [[ | 3839 | example = [[ |
| 3862 | function test() | 3840 | function test() |
| 3863 | bob.joe.larry = 23 | 3841 | bob.joe.larry = 23 |
| 3864 | end | 3842 | end |
| 3865 | 3843 | ||
| 3866 | -- memory will grow steadly | 3844 | -- memory will grow steadly |
| 3867 | for i = 1, math.huge do | 3845 | for i = 1, math.huge do |
| 3868 | pcall(test) | 3846 | pcall(test) |
| 3869 | if i % 100000 == 0 then | 3847 | if i % 100000 == 0 then |
| @@ -3892,7 +3870,7 @@ report = [[云风 Cloud Wu, 2017/08/15]], | |||
| 3892 | since = [[5.2]], | 3870 | since = [[5.2]], |
| 3893 | fix = nil, | 3871 | fix = nil, |
| 3894 | example = [[ | 3872 | example = [[ |
| 3895 | -- The following chunk, under a memory checker like valgrind, | 3873 | -- The following chunk, under a memory checker like valgrind, |
| 3896 | -- produces a memory access violation. | 3874 | -- produces a memory access violation. |
| 3897 | 3875 | ||
| 3898 | local a = setmetatable({}, {__mode = 'kv'}) | 3876 | local a = setmetatable({}, {__mode = 'kv'}) |
| @@ -4020,7 +3998,6 @@ patch = [[ | |||
| 4020 | ----------------------------------------------------------------- | 3998 | ----------------------------------------------------------------- |
| 4021 | -- Lua 5.3.5 | 3999 | -- Lua 5.3.5 |
| 4022 | 4000 | ||
| 4023 | --[=[ | ||
| 4024 | Bug{ | 4001 | Bug{ |
| 4025 | what = [[Long brackets with a huge number of '=' overflow some | 4002 | what = [[Long brackets with a huge number of '=' overflow some |
| 4026 | internal buffer arithmetic]], | 4003 | internal buffer arithmetic]], |
| @@ -4111,9 +4088,34 @@ patch = [[ | |||
| 4111 | } | 4088 | } |
| 4112 | ]] | 4089 | ]] |
| 4113 | } | 4090 | } |
| 4114 | ]=] | ||
| 4115 | 4091 | ||
| 4116 | 4092 | ||
| 4093 | Bug{ | ||
| 4094 | what = [[joining an upvalue with itself can cause a use-after-free crash]], | ||
| 4095 | report = [[Fady Othman, 2019/01/10]], | ||
| 4096 | since = [[5.3]], | ||
| 4097 | fix = nil, | ||
| 4098 | example = [[ | ||
| 4099 | -- the next code may crash the machine | ||
| 4100 | f=load(function() end) | ||
| 4101 | interesting={} | ||
| 4102 | interesting[0]=string.rep("A",512) | ||
| 4103 | debug.upvaluejoin(f,1,f,1) | ||
| 4104 | ]], | ||
| 4105 | patch = [[ | ||
| 4106 | --- a/lapi.c | ||
| 4107 | +++ b/lapi.c | ||
| 4108 | @@ -1289,6 +1289,8 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | ||
| 4109 | LClosure *f1; | ||
| 4110 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | ||
| 4111 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | ||
| 4112 | + if (*up1 == *up2) | ||
| 4113 | + return; | ||
| 4114 | luaC_upvdeccount(L, *up1); | ||
| 4115 | *up1 = *up2; | ||
| 4116 | (*up1)->refcount++; | ||
| 4117 | ]] | ||
| 4118 | } | ||
| 4117 | 4119 | ||
| 4118 | 4120 | ||
| 4119 | --[=[ | 4121 | --[=[ |
| @@ -1254,13 +1254,12 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |||
| 1254 | } | 1254 | } |
| 1255 | 1255 | ||
| 1256 | 1256 | ||
| 1257 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { | 1257 | static UpVal **getupvalref (lua_State *L, int fidx, int n) { |
| 1258 | LClosure *f; | 1258 | LClosure *f; |
| 1259 | StkId fi = index2addr(L, fidx); | 1259 | StkId fi = index2addr(L, fidx); |
| 1260 | api_check(L, ttisLclosure(fi), "Lua function expected"); | 1260 | api_check(L, ttisLclosure(fi), "Lua function expected"); |
| 1261 | f = clLvalue(fi); | 1261 | f = clLvalue(fi); |
| 1262 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); | 1262 | api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); |
| 1263 | if (pf) *pf = f; | ||
| 1264 | return &f->upvals[n - 1]; /* get its upvalue pointer */ | 1263 | return &f->upvals[n - 1]; /* get its upvalue pointer */ |
| 1265 | } | 1264 | } |
| 1266 | 1265 | ||
| @@ -1269,7 +1268,7 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | |||
| 1269 | StkId fi = index2addr(L, fidx); | 1268 | StkId fi = index2addr(L, fidx); |
| 1270 | switch (ttype(fi)) { | 1269 | switch (ttype(fi)) { |
| 1271 | case LUA_TLCL: { /* lua closure */ | 1270 | case LUA_TLCL: { /* lua closure */ |
| 1272 | return *getupvalref(L, fidx, n, NULL); | 1271 | return *getupvalref(L, fidx, n); |
| 1273 | } | 1272 | } |
| 1274 | case LUA_TCCL: { /* C closure */ | 1273 | case LUA_TCCL: { /* C closure */ |
| 1275 | CClosure *f = clCvalue(fi); | 1274 | CClosure *f = clCvalue(fi); |
| @@ -1286,9 +1285,10 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | |||
| 1286 | 1285 | ||
| 1287 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | 1286 | LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, |
| 1288 | int fidx2, int n2) { | 1287 | int fidx2, int n2) { |
| 1289 | LClosure *f1; | 1288 | UpVal **up1 = getupvalref(L, fidx1, n1); |
| 1290 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | 1289 | UpVal **up2 = getupvalref(L, fidx2, n2); |
| 1291 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | 1290 | if (*up1 == *up2) |
| 1291 | return; | ||
| 1292 | luaC_upvdeccount(L, *up1); | 1292 | luaC_upvdeccount(L, *up1); |
| 1293 | *up1 = *up2; | 1293 | *up1 = *up2; |
| 1294 | (*up1)->refcount++; | 1294 | (*up1)->refcount++; |
| @@ -58,9 +58,9 @@ MYLDFLAGS= $(LOCAL) -Wl,-E | |||
| 58 | MYLIBS= -ldl -lreadline | 58 | MYLIBS= -ldl -lreadline |
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | CC= clang-3.8 | 61 | CC= gcc |
| 62 | CFLAGS= -Wall -O2 $(MYCFLAGS) | 62 | CFLAGS= -Wall -O2 $(MYCFLAGS) |
| 63 | AR= ar rcu | 63 | AR= ar rc |
| 64 | RANLIB= ranlib | 64 | RANLIB= ranlib |
| 65 | RM= rm -f | 65 | RM= rm -f |
| 66 | 66 | ||
