aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2016-03-31 16:07:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2016-03-31 16:07:42 -0300
commit783aa8a9da5f32eb14b39d9332b41fa01ef81d52 (patch)
tree59bb622e13fb95b2c4b0e71c62d0ed67381ffc68 /lstrlib.c
parent8d4feb504f34c182ad991102d5ccd974b3a5f1b8 (diff)
downloadlua-783aa8a9da5f32eb14b39d9332b41fa01ef81d52.tar.gz
lua-783aa8a9da5f32eb14b39d9332b41fa01ef81d52.tar.bz2
lua-783aa8a9da5f32eb14b39d9332b41fa01ef81d52.zip
new way to avoid infinite loops in empty matches: "Python rule"
("Empty matches for the pattern are replaced only when not adjacent to a previous match")
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/lstrlib.c b/lstrlib.c
index ec757284..7f9cd00c 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.241 2016/03/23 17:12:17 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.242 2016/03/23 18:08:26 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*/
@@ -681,6 +681,7 @@ static int str_match (lua_State *L) {
681typedef struct GMatchState { 681typedef struct GMatchState {
682 const char *src; /* current position */ 682 const char *src; /* current position */
683 const char *p; /* pattern */ 683 const char *p; /* pattern */
684 const char *lastmatch; /* end of last match */
684 MatchState ms; /* match state */ 685 MatchState ms; /* match state */
685} GMatchState; 686} GMatchState;
686 687
@@ -692,9 +693,8 @@ static int gmatch_aux (lua_State *L) {
692 for (src = gm->src; src <= gm->ms.src_end; src++) { 693 for (src = gm->src; src <= gm->ms.src_end; src++) {
693 const char *e; 694 const char *e;
694 reprepstate(&gm->ms); 695 reprepstate(&gm->ms);
695 if ((e = match(&gm->ms, src, gm->p)) != NULL) { 696 if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
696 /* in empty matches, advance at least one position */ 697 gm->src = gm->lastmatch = e;
697 gm->src = (e == src) ? src + 1 : e;
698 return push_captures(&gm->ms, src, e); 698 return push_captures(&gm->ms, src, e);
699 } 699 }
700 } 700 }
@@ -710,7 +710,7 @@ static int gmatch (lua_State *L) {
710 lua_settop(L, 2); /* keep them on closure to avoid being collected */ 710 lua_settop(L, 2); /* keep them on closure to avoid being collected */
711 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); 711 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
712 prepstate(&gm->ms, L, s, ls, p, lp); 712 prepstate(&gm->ms, L, s, ls, p, lp);
713 gm->src = s; gm->p = p; 713 gm->src = s; gm->p = p; gm->lastmatch = NULL;
714 lua_pushcclosure(L, gmatch_aux, 3); 714 lua_pushcclosure(L, gmatch_aux, 3);
715 return 1; 715 return 1;
716} 716}
@@ -779,6 +779,7 @@ static int str_gsub (lua_State *L) {
779 size_t srcl, lp; 779 size_t srcl, lp;
780 const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ 780 const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
781 const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ 781 const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
782 const char *lastmatch = NULL; /* end of last match */
782 int tr = lua_type(L, 3); /* replacement type */ 783 int tr = lua_type(L, 3); /* replacement type */
783 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ 784 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
784 int anchor = (*p == '^'); 785 int anchor = (*p == '^');
@@ -796,12 +797,11 @@ static int str_gsub (lua_State *L) {
796 while (n < max_s) { 797 while (n < max_s) {
797 const char *e; 798 const char *e;
798 reprepstate(&ms); /* (re)prepare state for new match */ 799 reprepstate(&ms); /* (re)prepare state for new match */
799 if ((e = match(&ms, src, p)) != NULL) { /* match? */ 800 if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
800 n++; 801 n++;
801 add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ 802 add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
803 src = lastmatch = e;
802 } 804 }
803 if (e && e>src) /* non empty match? */
804 src = e; /* skip it */
805 else if (src < ms.src_end) /* otherwise, skip one character */ 805 else if (src < ms.src_end) /* otherwise, skip one character */
806 luaL_addchar(&b, *src++); 806 luaL_addchar(&b, *src++);
807 else break; /* end of subject */ 807 else break; /* end of subject */