aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lstrlib.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 379fd20f..97139613 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.160 2010/12/10 19:03:46 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.161 2010/12/20 17:25:36 roberto Exp roberto $
3** Standard library for string operations and pattern-matching 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -101,15 +101,29 @@ static int str_upper (lua_State *L) {
101 return 1; 101 return 1;
102} 102}
103 103
104
105/* reasonable limit to avoid arithmetic overflow */
106#define MAXSIZE ((~(size_t)0) >> 1)
107
104static int str_rep (lua_State *L) { 108static int str_rep (lua_State *L) {
105 size_t l; 109 size_t l, lsep;
106 luaL_Buffer b;
107 const char *s = luaL_checklstring(L, 1, &l); 110 const char *s = luaL_checklstring(L, 1, &l);
108 int n = luaL_checkint(L, 2); 111 int n = luaL_checkint(L, 2);
109 luaL_buffinit(L, &b); 112 const char *sep = luaL_optlstring(L, 3, "", &lsep);
110 while (n-- > 0) 113 if (n <= 0) lua_pushliteral(L, "");
111 luaL_addlstring(&b, s, l); 114 else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */
112 luaL_pushresult(&b); 115 return luaL_error(L, "resulting string too large");
116 else {
117 size_t totallen = n * l + (n - 1) * lsep;
118 luaL_Buffer b;
119 char *p = luaL_buffinitsize(L, &b, totallen);
120 while (n-- > 1) { /* first n-1 copies (followed by separator) */
121 memcpy(p, s, l); p += l;
122 memcpy(p, sep, lsep); p += lsep;
123 }
124 memcpy(p, s, l); /* last copy (not followed by separator) */
125 luaL_pushresultsize(&b, totallen);
126 }
113 return 1; 127 return 1;
114} 128}
115 129
@@ -125,7 +139,7 @@ static int str_byte (lua_State *L) {
125 if (posi > pose) return 0; /* empty interval; return no values */ 139 if (posi > pose) return 0; /* empty interval; return no values */
126 n = (int)(pose - posi + 1); 140 n = (int)(pose - posi + 1);
127 if (posi + n <= pose) /* overflow? */ 141 if (posi + n <= pose) /* overflow? */
128 luaL_error(L, "string slice too long"); 142 return luaL_error(L, "string slice too long");
129 luaL_checkstack(L, n, "string slice too long"); 143 luaL_checkstack(L, n, "string slice too long");
130 for (i=0; i<n; i++) 144 for (i=0; i<n; i++)
131 lua_pushinteger(L, uchar(s[posi+i-1])); 145 lua_pushinteger(L, uchar(s[posi+i-1]));
@@ -161,7 +175,7 @@ static int str_dump (lua_State *L) {
161 lua_settop(L, 1); 175 lua_settop(L, 1);
162 luaL_buffinit(L,&b); 176 luaL_buffinit(L,&b);
163 if (lua_dump(L, writer, &b) != 0) 177 if (lua_dump(L, writer, &b) != 0)
164 luaL_error(L, "unable to dump given function"); 178 return luaL_error(L, "unable to dump given function");
165 luaL_pushresult(&b); 179 luaL_pushresult(&b);
166 return 1; 180 return 1;
167} 181}