diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-09-22 13:10:39 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-09-22 13:10:39 -0300 |
| commit | deac067ed39a44c001599c0d15de09872496b2aa (patch) | |
| tree | d7373651e7d54a8ca5ffa4841379a4d9149164aa | |
| parent | 2ff34717227b8046b0fdcb96206f11f5e888664e (diff) | |
| download | lua-deac067ed39a44c001599c0d15de09872496b2aa.tar.gz lua-deac067ed39a44c001599c0d15de09872496b2aa.tar.bz2 lua-deac067ed39a44c001599c0d15de09872496b2aa.zip | |
Avoid overflows when incrementing parameters in C
Any C function can receive maxinteger as an integer argument, and
therefore cannot increment it without some care (e.g., doing unsigned
arithmetic as the core does).
| -rw-r--r-- | lauxlib.h | 8 | ||||
| -rw-r--r-- | lbaselib.c | 3 | ||||
| -rw-r--r-- | ltablib.c | 3 | ||||
| -rw-r--r-- | lutf8lib.c | 11 | ||||
| -rw-r--r-- | testes/nextvar.lua | 17 | ||||
| -rw-r--r-- | testes/utf8.lua | 6 |
6 files changed, 39 insertions, 9 deletions
| @@ -154,6 +154,14 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | |||
| 154 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) | 154 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) |
| 155 | 155 | ||
| 156 | 156 | ||
| 157 | /* | ||
| 158 | ** Perform arithmetic operations on lua_Integer values with wrap-around | ||
| 159 | ** semantics, as the Lua core does. | ||
| 160 | */ | ||
| 161 | #define luaL_intop(op,v1,v2) \ | ||
| 162 | ((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2))) | ||
| 163 | |||
| 164 | |||
| 157 | /* push the value used to represent failure/error */ | 165 | /* push the value used to represent failure/error */ |
| 158 | #define luaL_pushfail(L) lua_pushnil(L) | 166 | #define luaL_pushfail(L) lua_pushnil(L) |
| 159 | 167 | ||
| @@ -285,7 +285,8 @@ static int luaB_pairs (lua_State *L) { | |||
| 285 | ** Traversal function for 'ipairs' | 285 | ** Traversal function for 'ipairs' |
| 286 | */ | 286 | */ |
| 287 | static int ipairsaux (lua_State *L) { | 287 | static int ipairsaux (lua_State *L) { |
| 288 | lua_Integer i = luaL_checkinteger(L, 2) + 1; | 288 | lua_Integer i = luaL_checkinteger(L, 2); |
| 289 | i = luaL_intop(+, i, 1); | ||
| 289 | lua_pushinteger(L, i); | 290 | lua_pushinteger(L, i); |
| 290 | return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; | 291 | return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; |
| 291 | } | 292 | } |
| @@ -59,8 +59,9 @@ static void checktab (lua_State *L, int arg, int what) { | |||
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | static int tinsert (lua_State *L) { | 61 | static int tinsert (lua_State *L) { |
| 62 | lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ | ||
| 63 | lua_Integer pos; /* where to insert new element */ | 62 | lua_Integer pos; /* where to insert new element */ |
| 63 | lua_Integer e = aux_getn(L, 1, TAB_RW); | ||
| 64 | e = luaL_intop(+, e, 1); /* first empty element */ | ||
| 64 | switch (lua_gettop(L)) { | 65 | switch (lua_gettop(L)) { |
| 65 | case 2: { /* called with only 2 arguments */ | 66 | case 2: { /* called with only 2 arguments */ |
| 66 | pos = e; /* insert new element at the end */ | 67 | pos = e; /* insert new element at the end */ |
| @@ -224,14 +224,11 @@ static int byteoffset (lua_State *L) { | |||
| 224 | static int iter_aux (lua_State *L, int strict) { | 224 | static int iter_aux (lua_State *L, int strict) { |
| 225 | size_t len; | 225 | size_t len; |
| 226 | const char *s = luaL_checklstring(L, 1, &len); | 226 | const char *s = luaL_checklstring(L, 1, &len); |
| 227 | lua_Integer n = lua_tointeger(L, 2) - 1; | 227 | lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); |
| 228 | if (n < 0) /* first iteration? */ | 228 | if (n < len) { |
| 229 | n = 0; /* start from here */ | 229 | while (iscont(s + n)) n++; /* skip continuation bytes */ |
| 230 | else if (n < (lua_Integer)len) { | ||
| 231 | n++; /* skip current byte */ | ||
| 232 | while (iscont(s + n)) n++; /* and its continuations */ | ||
| 233 | } | 230 | } |
| 234 | if (n >= (lua_Integer)len) | 231 | if (n >= len) /* (also handles original 'n' being negative) */ |
| 235 | return 0; /* no more codepoints */ | 232 | return 0; /* no more codepoints */ |
| 236 | else { | 233 | else { |
| 237 | utfint code; | 234 | utfint code; |
diff --git a/testes/nextvar.lua b/testes/nextvar.lua index 076f6361..9e23e572 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua | |||
| @@ -43,6 +43,14 @@ assert(i == 4) | |||
| 43 | assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{}) | 43 | assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{}) |
| 44 | 44 | ||
| 45 | 45 | ||
| 46 | do -- overflow (must wrap-around) | ||
| 47 | local f = ipairs{} | ||
| 48 | local k, v = f({[math.mininteger] = 10}, math.maxinteger) | ||
| 49 | assert(k == math.mininteger and v == 10) | ||
| 50 | k, v = f({[math.mininteger] = 10}, k) | ||
| 51 | assert(k == nil) | ||
| 52 | end | ||
| 53 | |||
| 46 | if not T then | 54 | if not T then |
| 47 | (Message or print) | 55 | (Message or print) |
| 48 | ('\n >>> testC not active: skipping tests for table sizes <<<\n') | 56 | ('\n >>> testC not active: skipping tests for table sizes <<<\n') |
| @@ -499,6 +507,15 @@ do -- testing table library with metamethods | |||
| 499 | end | 507 | end |
| 500 | 508 | ||
| 501 | 509 | ||
| 510 | do -- testing overflow in table.insert (must wrap-around) | ||
| 511 | |||
| 512 | local t = setmetatable({}, | ||
| 513 | {__len = function () return math.maxinteger end}) | ||
| 514 | table.insert(t, 20) | ||
| 515 | local k, v = next(t) | ||
| 516 | assert(k == math.mininteger and v == 20) | ||
| 517 | end | ||
| 518 | |||
| 502 | if not T then | 519 | if not T then |
| 503 | (Message or print) | 520 | (Message or print) |
| 504 | ('\n >>> testC not active: skipping tests for table library on non-tables <<<\n') | 521 | ('\n >>> testC not active: skipping tests for table library on non-tables <<<\n') |
diff --git a/testes/utf8.lua b/testes/utf8.lua index 6010d1ad..461e223c 100644 --- a/testes/utf8.lua +++ b/testes/utf8.lua | |||
| @@ -112,6 +112,12 @@ do | |||
| 112 | end | 112 | end |
| 113 | errorcodes("ab\xff") | 113 | errorcodes("ab\xff") |
| 114 | errorcodes("\u{110000}") | 114 | errorcodes("\u{110000}") |
| 115 | |||
| 116 | -- calling interation function with invalid arguments | ||
| 117 | local f = utf8.codes("") | ||
| 118 | assert(f("", 2) == nil) | ||
| 119 | assert(f("", -1) == nil) | ||
| 120 | assert(f("", math.mininteger) == nil) | ||
| 115 | end | 121 | end |
| 116 | 122 | ||
| 117 | -- error in initial position for offset | 123 | -- error in initial position for offset |
