summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-02-27 12:42:16 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-02-27 12:42:16 -0300
commitd97fe6ed31d4b274c88c996b0c06da597a455149 (patch)
treea37297862273c9e44197026923bc4a4c3d1e16f9
parentf53caf1f863f140de1c1af51906e658c9fb7d7d6 (diff)
downloadlpeg-d97fe6ed31d4b274c88c996b0c06da597a455149.tar.gz
lpeg-d97fe6ed31d4b274c88c996b0c06da597a455149.tar.bz2
lpeg-d97fe6ed31d4b274c88c996b0c06da597a455149.zip
Fixed bug when resizing capture list
Fixed the bug reported in http://lua-users.org/lists/lua-l/2018-11/msg00080.html The field 's' of the open group of captures inside a run-time capture was being reused by the open group of the results of the run-time capture, even though that open-group entry was being removed from the list and then added again.
-rw-r--r--lpcap.c10
-rw-r--r--lpvm.c83
2 files changed, 51 insertions, 42 deletions
diff --git a/lpcap.c b/lpcap.c
index 1c2af0b..b332fde 100644
--- a/lpcap.c
+++ b/lpcap.c
@@ -271,15 +271,15 @@ int finddyncap (Capture *cap, Capture *last) {
271 271
272 272
273/* 273/*
274** Calls a runtime capture. Returns number of captures removed by 274** Calls a runtime capture. Returns number of captures "removed" by the
275** the call, including the initial Cgroup. (Captures to be added are 275** call, that is, those inside the group capture. Captures to be added
276** on the Lua stack.) 276** are on the Lua stack.
277*/ 277*/
278int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { 278int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
279 int n, id; 279 int n, id;
280 lua_State *L = cs->L; 280 lua_State *L = cs->L;
281 int otop = lua_gettop(L); 281 int otop = lua_gettop(L);
282 Capture *open = findopen(close); 282 Capture *open = findopen(close); /* get open group capture */
283 assert(captype(open) == Cgroup); 283 assert(captype(open) == Cgroup);
284 id = finddyncap(open, close); /* get first dynamic capture argument */ 284 id = finddyncap(open, close); /* get first dynamic capture argument */
285 close->kind = Cclose; /* closes the group */ 285 close->kind = Cclose; /* closes the group */
@@ -299,7 +299,7 @@ int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
299 } 299 }
300 else 300 else
301 *rem = 0; /* no dynamic captures removed */ 301 *rem = 0; /* no dynamic captures removed */
302 return close - open; /* number of captures of all kinds removed */ 302 return close - open - 1; /* number of captures to be removed */
303} 303}
304 304
305 305
diff --git a/lpvm.c b/lpvm.c
index 813d3fb..737418c 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -45,18 +45,29 @@ typedef struct Stack {
45 45
46 46
47/* 47/*
48** Make the size of the array of captures 'cap' twice as large as needed 48** Ensures the size of array 'capture' (with size '*capsize' and
49** (which is 'captop'). ('n' is the number of new elements.) 49** 'captop' elements being used) is enough to accomodate 'n' extra
50** elements plus one. (Because several opcodes add stuff to the capture
51** array, it is simpler to ensure the array always has at least one free
52** slot upfront and check its size later.)
50*/ 53*/
51static Capture *doublecap (lua_State *L, Capture *cap, int captop, 54static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
52 int n, int ptop) { 55 int captop, int n, int ptop) {
53 Capture *newc; 56 if (*capsize - captop > n)
54 if (captop >= INT_MAX/((int)sizeof(Capture) * 2)) 57 return capture; /* no need to grow array */
55 luaL_error(L, "too many captures"); 58 else { /* must grow */
56 newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture)); 59 Capture *newc;
57 memcpy(newc, cap, (captop - n) * sizeof(Capture)); 60 int newsize = captop + n + 1; /* minimum size needed */
58 lua_replace(L, caplistidx(ptop)); 61 if (newsize < INT_MAX/((int)sizeof(Capture) * 2))
59 return newc; 62 newsize *= 2; /* twice that size, if not too big */
63 else if (newsize >= INT_MAX/((int)sizeof(Capture)))
64 luaL_error(L, "too many captures");
65 newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
66 memcpy(newc, capture, captop * sizeof(Capture));
67 *capsize = newsize;
68 lua_replace(L, caplistidx(ptop));
69 return newc;
70 }
60} 71}
61 72
62 73
@@ -109,24 +120,24 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
109 120
110 121
111/* 122/*
112** Add capture values returned by a dynamic capture to the capture list 123** Add capture values returned by a dynamic capture to the list
113** 'base', nested inside a group capture. 'fd' indexes the first capture 124** 'capture', nested inside a group. 'fd' indexes the first capture
114** value, 'n' is the number of values (at least 1). 125** value, 'n' is the number of values (at least 1). The open group
126** capture is already in 'capture', before the place for the new entries.
115*/ 127*/
116static void adddyncaptures (const char *s, Capture *base, int n, int fd) { 128static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {
117 int i; 129 int i;
118 base[0].kind = Cgroup; /* create group capture */ 130 assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);
119 base[0].siz = 0; 131 capture[-1].idx = 0; /* make group capture an anonymous group */
120 base[0].idx = 0; /* make it an anonymous group */ 132 for (i = 0; i < n; i++) { /* add runtime captures */
121 for (i = 1; i <= n; i++) { /* add runtime captures */ 133 capture[i].kind = Cruntime;
122 base[i].kind = Cruntime; 134 capture[i].siz = 1; /* mark it as closed */
123 base[i].siz = 1; /* mark it as closed */ 135 capture[i].idx = fd + i; /* stack index of capture value */
124 base[i].idx = fd + i - 1; /* stack index of capture value */ 136 capture[i].s = s;
125 base[i].s = s;
126 } 137 }
127 base[i].kind = Cclose; /* close group */ 138 capture[n].kind = Cclose; /* close group */
128 base[i].siz = 1; 139 capture[n].siz = 1;
129 base[i].s = s; 140 capture[n].s = s;
130} 141}
131 142
132 143
@@ -308,15 +319,15 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
308 s = o + res; /* else update current position */ 319 s = o + res; /* else update current position */
309 n = lua_gettop(L) - fr + 1; /* number of new captures */ 320 n = lua_gettop(L) - fr + 1; /* number of new captures */
310 ndyncap += n; /* update number of dynamic captures */ 321 ndyncap += n; /* update number of dynamic captures */
311 if (n > 0) { /* any new capture? */ 322 if (n == 0) /* no new captures? */
323 captop--; /* remove open group */
324 else { /* new captures; keep original open group */
312 if (fr + n >= SHRT_MAX) 325 if (fr + n >= SHRT_MAX)
313 luaL_error(L, "too many results in match-time capture"); 326 luaL_error(L, "too many results in match-time capture");
314 if ((captop += n + 2) >= capsize) { 327 /* add new captures + close group to 'capture' list */
315 capture = doublecap(L, capture, captop, n + 2, ptop); 328 capture = growcap(L, capture, &capsize, captop, n + 1, ptop);
316 capsize = 2 * captop; 329 adddyncaptures(s, capture + captop, n, fr);
317 } 330 captop += n + 1; /* new captures + close group */
318 /* add new captures to 'capture' list */
319 adddyncaptures(s, capture + captop - n - 2, n, fr);
320 } 331 }
321 p++; 332 p++;
322 continue; 333 continue;
@@ -348,10 +359,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
348 pushcapture: { 359 pushcapture: {
349 capture[captop].idx = p->i.key; 360 capture[captop].idx = p->i.key;
350 capture[captop].kind = getkind(p); 361 capture[captop].kind = getkind(p);
351 if (++captop >= capsize) { 362 captop++;
352 capture = doublecap(L, capture, captop, 0, ptop); 363 capture = growcap(L, capture, &capsize, captop, 0, ptop);
353 capsize = 2 * captop;
354 }
355 p++; 364 p++;
356 continue; 365 continue;
357 } 366 }