aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 8056c6ff..d9735903 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -132,27 +132,31 @@ static int str_upper (lua_State *L) {
132} 132}
133 133
134 134
135/*
136** MAX_SIZE is limited both by size_t and lua_Integer.
137** When x <= MAX_SIZE, x can be safely cast to size_t or lua_Integer.
138*/
135static int str_rep (lua_State *L) { 139static int str_rep (lua_State *L) {
136 size_t l, lsep; 140 size_t len, lsep;
137 const char *s = luaL_checklstring(L, 1, &l); 141 const char *s = luaL_checklstring(L, 1, &len);
138 lua_Integer n = luaL_checkinteger(L, 2); 142 lua_Integer n = luaL_checkinteger(L, 2);
139 const char *sep = luaL_optlstring(L, 3, "", &lsep); 143 const char *sep = luaL_optlstring(L, 3, "", &lsep);
140 if (n <= 0) 144 if (n <= 0)
141 lua_pushliteral(L, ""); 145 lua_pushliteral(L, "");
142 else if (l_unlikely(l + lsep < l || l + lsep > MAX_SIZE / cast_sizet(n))) 146 else if (l_unlikely(len > MAX_SIZE - lsep ||
147 cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n))
143 return luaL_error(L, "resulting string too large"); 148 return luaL_error(L, "resulting string too large");
144 else { 149 else {
145 size_t totallen = ((size_t)n * (l + lsep)) - lsep; 150 size_t totallen = (cast_sizet(n) * (len + lsep)) - lsep;
146 luaL_Buffer b; 151 luaL_Buffer b;
147 char *p = luaL_buffinitsize(L, &b, totallen); 152 char *p = luaL_buffinitsize(L, &b, totallen);
148 while (n-- > 1) { /* first n-1 copies (followed by separator) */ 153 while (n-- > 1) { /* first n-1 copies (followed by separator) */
149 memcpy(p, s, l * sizeof(char)); p += l; 154 memcpy(p, s, len * sizeof(char)); p += len;
150 if (lsep > 0) { /* empty 'memcpy' is not that cheap */ 155 if (lsep > 0) { /* empty 'memcpy' is not that cheap */
151 memcpy(p, sep, lsep * sizeof(char)); 156 memcpy(p, sep, lsep * sizeof(char)); p += lsep;
152 p += lsep;
153 } 157 }
154 } 158 }
155 memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ 159 memcpy(p, s, len * sizeof(char)); /* last copy without separator */
156 luaL_pushresultsize(&b, totallen); 160 luaL_pushresultsize(&b, totallen);
157 } 161 }
158 return 1; 162 return 1;