aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2022-02-22 14:01:19 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2022-02-22 14:01:19 -0300
commit1b55119610ba5a6752c768c2f997a90c0ffc0546 (patch)
tree9075c8938dd14ecc56859e59928e8df3eb326694
parentc2680687d148820847607e13ed7100e60d94c79e (diff)
downloadlpeg-1b55119610ba5a6752c768c2f997a90c0ffc0546.tar.gz
lpeg-1b55119610ba5a6752c768c2f997a90c0ffc0546.tar.bz2
lpeg-1b55119610ba5a6752c768c2f997a90c0ffc0546.zip
Better computation of size limit in 'growcap'
Old code mixed size in elements (counted with 'int's) with size in bytes (division by the size of an element). Moreover, when it could not double the size, it grew it one by one, which is undoable performance-wise.
-rw-r--r--lpvm.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/lpvm.c b/lpvm.c
index af9e617..f7c7e62 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -80,16 +80,25 @@ typedef struct Stack {
80** array, it is simpler to ensure the array always has at least one free 80** array, it is simpler to ensure the array always has at least one free
81** slot upfront and check its size later.) 81** slot upfront and check its size later.)
82*/ 82*/
83
84/* new size in number of elements cannot overflow integers, and new
85 size in bytes cannot overflow size_t. */
86#define MAXNEWSIZE \
87 (((size_t)INT_MAX) <= (~(size_t)0 / sizeof(Capture)) ? \
88 ((size_t)INT_MAX) : (~(size_t)0 / sizeof(Capture)))
89
83static Capture *growcap (lua_State *L, Capture *capture, int *capsize, 90static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
84 int captop, int n, int ptop) { 91 int captop, int n, int ptop) {
85 if (*capsize - captop > n) 92 if (*capsize - captop > n)
86 return capture; /* no need to grow array */ 93 return capture; /* no need to grow array */
87 else { /* must grow */ 94 else { /* must grow */
88 Capture *newc; 95 Capture *newc;
89 int newsize = captop + n + 1; /* minimum size needed */ 96 unsigned int newsize = captop + n + 1; /* minimum size needed */
90 if (newsize < INT_MAX/((int)sizeof(Capture) * 2)) 97 if (newsize < MAXNEWSIZE / 2)
91 newsize *= 2; /* twice that size, if not too big */ 98 newsize *= 2; /* twice that size, if not too big */
92 else if (newsize >= INT_MAX/((int)sizeof(Capture))) 99 else if (newsize < (MAXNEWSIZE / 9) * 8)
100 newsize += newsize / 8; /* else, try 9/8 that size */
101 else
93 luaL_error(L, "too many captures"); 102 luaL_error(L, "too many captures");
94 newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture)); 103 newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
95 memcpy(newc, capture, captop * sizeof(Capture)); 104 memcpy(newc, capture, captop * sizeof(Capture));
@@ -329,7 +338,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
329 case IFailTwice: 338 case IFailTwice:
330 assert(stack > getstackbase(L, ptop)); 339 assert(stack > getstackbase(L, ptop));
331 stack--; 340 stack--;
332 /* go through */ 341 /* FALLTHROUGH */
333 case IFail: 342 case IFail:
334 fail: { /* pattern failed: try to backtrack */ 343 fail: { /* pattern failed: try to backtrack */
335 do { /* remove pending calls */ 344 do { /* remove pending calls */