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 | ||