diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-02-22 14:01:19 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-02-22 14:01:19 -0300 |
commit | 1b55119610ba5a6752c768c2f997a90c0ffc0546 (patch) | |
tree | 9075c8938dd14ecc56859e59928e8df3eb326694 /lpvm.c | |
parent | c2680687d148820847607e13ed7100e60d94c79e (diff) | |
download | lpeg-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.
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 17 |
1 files changed, 13 insertions, 4 deletions
@@ -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 | |||
83 | static Capture *growcap (lua_State *L, Capture *capture, int *capsize, | 90 | static 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 */ |