From 7106c491dddbfc7b9986c3c91214acd56b066d7f Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 12 Jan 2011 18:36:01 -0200 Subject: 'sep' argument to 'string.rep' + 'string.rep' preallocates entire buffer before creating resulting string --- lstrlib.c | 32 +++++++++++++++++++++++--------- 1 file 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 @@ /* -** $Id: lstrlib.c,v 1.160 2010/12/10 19:03:46 roberto Exp roberto $ +** $Id: lstrlib.c,v 1.161 2010/12/20 17:25:36 roberto Exp roberto $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -101,15 +101,29 @@ static int str_upper (lua_State *L) { return 1; } + +/* reasonable limit to avoid arithmetic overflow */ +#define MAXSIZE ((~(size_t)0) >> 1) + static int str_rep (lua_State *L) { - size_t l; - luaL_Buffer b; + size_t l, lsep; const char *s = luaL_checklstring(L, 1, &l); int n = luaL_checkint(L, 2); - luaL_buffinit(L, &b); - while (n-- > 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); + const char *sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = n * l + (n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l); p += l; + memcpy(p, sep, lsep); p += lsep; + } + memcpy(p, s, l); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } return 1; } @@ -125,7 +139,7 @@ static int str_byte (lua_State *L) { if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); if (posi + n <= pose) /* overflow? */ - luaL_error(L, "string slice too long"); + return luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i