BUG: 'gsub' may go wild when wrongly called without its third

> argument and with a large subject.
This commit is contained in:
Roberto Ierusalimschy 2007-10-29 13:51:10 -02:00
parent 2fa476655f
commit c06cc60946
2 changed files with 41 additions and 11 deletions

31
bugs
View File

@ -1538,6 +1538,37 @@ lua.c:
]], ]],
} }
Bug{
what = [['gsub' may go wild when wrongly called without its third
argument and with a large subject]],
report = [[Florian Berger, on 10/2007]],
since = [[5.1]],
example = [[
x = string.rep('a', 10000) .. string.rep('b', 10000)
print(#string.gsub(x, 'b'))
]],
patch = [[
lstrlib.c:
@@ -631,6 +631,2 @@
}
- default: {
- luaL_argerror(L, 3, "string/function/table expected");
- return;
- }
}
@@ -650,2 +646,3 @@
const char *p = luaL_checkstring(L, 2);
+ int tr = lua_type(L, 3);
int max_s = luaL_optint(L, 4, srcl+1);
@@ -655,2 +652,5 @@
luaL_Buffer b;
+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
+ "string/function/table expected");
luaL_buffinit(L, &b);
]],
}
Bug{ Bug{
what = [[ ]], what = [[ ]],
report = [[ , on ]], report = [[ , on ]],

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.136 2007/02/07 17:53:08 roberto Exp roberto $ ** $Id: lstrlib.c,v 1.137 2007/10/25 19:30:36 roberto Exp roberto $
** Standard library for string operations and pattern-matching ** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -611,14 +611,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
const char *e) { const char *e, int tr) {
lua_State *L = ms->L; lua_State *L = ms->L;
switch (lua_type(L, 3)) { switch (tr) {
case LUA_TNUMBER:
case LUA_TSTRING: {
add_s(ms, b, s, e);
return;
}
case LUA_TFUNCTION: { case LUA_TFUNCTION: {
int n; int n;
lua_pushvalue(L, 3); lua_pushvalue(L, 3);
@ -631,8 +626,8 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
lua_gettable(L, 3); lua_gettable(L, 3);
break; break;
} }
default: { default: { /* LUA_TNUMBER or LUA_TSTRING */
luaL_argerror(L, 3, "string/function/table expected"); add_s(ms, b, s, e);
return; return;
} }
} }
@ -650,11 +645,15 @@ static int str_gsub (lua_State *L) {
size_t srcl; size_t srcl;
const char *src = luaL_checklstring(L, 1, &srcl); const char *src = luaL_checklstring(L, 1, &srcl);
const char *p = luaL_checkstring(L, 2); const char *p = luaL_checkstring(L, 2);
int tr = lua_type(L, 3);
size_t max_s = luaL_optinteger(L, 4, srcl+1); size_t max_s = luaL_optinteger(L, 4, srcl+1);
int anchor = (*p == '^') ? (p++, 1) : 0; int anchor = (*p == '^') ? (p++, 1) : 0;
size_t n = 0; size_t n = 0;
MatchState ms; MatchState ms;
luaL_Buffer b; luaL_Buffer b;
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
"string/function/table expected");
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
ms.L = L; ms.L = L;
ms.src_init = src; ms.src_init = src;
@ -665,7 +664,7 @@ static int str_gsub (lua_State *L) {
e = match(&ms, src, p); e = match(&ms, src, p);
if (e) { if (e) {
n++; n++;
add_value(&ms, &b, src, e); add_value(&ms, &b, src, e, tr);
} }
if (e && e>src) /* non empty match? */ if (e && e>src) /* non empty match? */
src = e; /* skip it */ src = e; /* skip it */