aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-09-22 13:10:39 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-09-22 13:10:39 -0300
commitdeac067ed39a44c001599c0d15de09872496b2aa (patch)
treed7373651e7d54a8ca5ffa4841379a4d9149164aa
parent2ff34717227b8046b0fdcb96206f11f5e888664e (diff)
downloadlua-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.h8
-rw-r--r--lbaselib.c3
-rw-r--r--ltablib.c3
-rw-r--r--lutf8lib.c11
-rw-r--r--testes/nextvar.lua17
-rw-r--r--testes/utf8.lua6
6 files changed, 39 insertions, 9 deletions
diff --git a/lauxlib.h b/lauxlib.h
index 72f70e7d..6f9695e8 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -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
diff --git a/lbaselib.c b/lbaselib.c
index fd6687e6..912c4cc6 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -285,7 +285,8 @@ static int luaB_pairs (lua_State *L) {
285** Traversal function for 'ipairs' 285** Traversal function for 'ipairs'
286*/ 286*/
287static int ipairsaux (lua_State *L) { 287static 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}
diff --git a/ltablib.c b/ltablib.c
index dbfe2509..868d78fd 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -59,8 +59,9 @@ static void checktab (lua_State *L, int arg, int what) {
59 59
60 60
61static int tinsert (lua_State *L) { 61static 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 */
diff --git a/lutf8lib.c b/lutf8lib.c
index 901d985f..e7bf098f 100644
--- a/lutf8lib.c
+++ b/lutf8lib.c
@@ -224,14 +224,11 @@ static int byteoffset (lua_State *L) {
224static int iter_aux (lua_State *L, int strict) { 224static 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)
43assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{}) 43assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{})
44 44
45 45
46do -- 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)
52end
53
46if not T then 54if 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
499end 507end
500 508
501 509
510do -- 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)
517end
518
502if not T then 519if 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)
115end 121end
116 122
117-- error in initial position for offset 123-- error in initial position for offset