浏览代码

BUG: 'gsub' may go wild when wrongly called without its third
> argument and with a large subject.

Roberto Ierusalimschy 18 年之前
父节点
当前提交
c06cc60946
共有 2 个文件被更改,包括 41 次插入11 次删除
  1. 31 0
      bugs
  2. 10 11
      lstrlib.c

+ 31 - 0
bugs

@@ -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{
 what = [[ ]],
 report = [[ , on ]],

+ 10 - 11
lstrlib.c

@@ -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
 ** 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,
-                                                       const char *e) {
+                                       const char *e, int tr) {
   lua_State *L = ms->L;
-  switch (lua_type(L, 3)) {
-    case LUA_TNUMBER:
-    case LUA_TSTRING: {
-      add_s(ms, b, s, e);
-      return;
-    }
+  switch (tr) {
     case LUA_TFUNCTION: {
       int n;
       lua_pushvalue(L, 3);
@@ -631,8 +626,8 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
       lua_gettable(L, 3);
       break;
     }
-    default: {
-      luaL_argerror(L, 3, "string/function/table expected");
+    default: {  /* LUA_TNUMBER or LUA_TSTRING */
+      add_s(ms, b, s, e);
       return;
     }
   }
@@ -650,11 +645,15 @@ static int str_gsub (lua_State *L) {
   size_t srcl;
   const char *src = luaL_checklstring(L, 1, &srcl);
   const char *p = luaL_checkstring(L, 2);
+  int tr = lua_type(L, 3);
   size_t max_s = luaL_optinteger(L, 4, srcl+1);
   int anchor = (*p == '^') ? (p++, 1) : 0;
   size_t n = 0;
   MatchState ms;
   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);
   ms.L = L;
   ms.src_init = src;
@@ -665,7 +664,7 @@ static int str_gsub (lua_State *L) {
     e = match(&ms, src, p);
     if (e) {
       n++;
-      add_value(&ms, &b, src, e);
+      add_value(&ms, &b, src, e, tr);
     }
     if (e && e>src) /* non empty match? */
       src = e;  /* skip it */