1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
--- lstrlib.c 2013-02-27 17:27:45.973598391 -0800
+++ luasandbox_lstrlib.c 2013-02-27 17:58:33.809497263 -0800
@@ -19,6 +19,12 @@
#include "lauxlib.h"
#include "lualib.h"
+#ifdef LUAI_MAXCALLS
+#define LUASANDBOX_MAX_MATCH_DEPTH LUAI_MAXCALLS
+#else
+#define LUASANDBOX_MAX_MATCH_DEPTH 20000
+#endif
+
/* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c))
@@ -176,6 +182,7 @@
const char *init;
ptrdiff_t len;
} capture[LUA_MAXCAPTURES];
+ int depth; /* the current recursion depth of match() */
} MatchState;
@@ -361,24 +368,44 @@
else return NULL;
}
+static int do_nothing(lua_State * L) {
+ return 0;
+}
+
+#define MATCH_RETURN(r) { \
+ const char * result = (r); \
+ --ms->depth; \
+ return result; \
+}
static const char *match (MatchState *ms, const char *s, const char *p) {
+ /* If there is a call hook, trigger it now so that it's possible to
+ * interrupt long-running recursive match operations */
+ if (lua_gethookmask(ms->L) & LUA_MASKCALL) {
+ lua_pushcfunction(ms->L, do_nothing);
+ lua_call(ms->L, 0, 0);
+ }
+
+ if (++ms->depth > LUASANDBOX_MAX_MATCH_DEPTH) {
+ luaL_error(ms->L, "recursion depth limit exceeded");
+ }
init: /* using goto's to optimize tail recursion */
switch (*p) {
case '(': { /* start capture */
- if (*(p+1) == ')') /* position capture? */
- return start_capture(ms, s, p+2, CAP_POSITION);
- else
- return start_capture(ms, s, p+1, CAP_UNFINISHED);
- }
+ if (*(p+1) == ')') { /* position capture? */
+ MATCH_RETURN(start_capture(ms, s, p+2, CAP_POSITION));
+ } else {
+ MATCH_RETURN(start_capture(ms, s, p+1, CAP_UNFINISHED));
+ }
+ }
case ')': { /* end capture */
- return end_capture(ms, s, p+1);
+ MATCH_RETURN(end_capture(ms, s, p+1));
}
case L_ESC: {
switch (*(p+1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2);
- if (s == NULL) return NULL;
+ if (s == NULL) MATCH_RETURN(NULL);
p+=4; goto init; /* else return match(ms, s, p+4); */
}
case 'f': { /* frontier? */
@@ -390,13 +417,13 @@
ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) ||
- !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
+ !matchbracketclass(uchar(*s), p, ep-1)) MATCH_RETURN(NULL);
p=ep; goto init; /* else return match(ms, s, ep); */
}
default: {
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
s = match_capture(ms, s, uchar(*(p+1)));
- if (s == NULL) return NULL;
+ if (s == NULL) MATCH_RETURN(NULL);
p+=2; goto init; /* else return match(ms, s, p+2) */
}
goto dflt; /* case default */
@@ -404,12 +431,12 @@
}
}
case '\0': { /* end of pattern */
- return s; /* match succeeded */
+ MATCH_RETURN(s); /* match succeeded */
}
case '$': {
- if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
- return (s == ms->src_end) ? s : NULL; /* check end of string */
- else goto dflt;
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
+ MATCH_RETURN((s == ms->src_end) ? s : NULL); /* check end of string */
+ goto dflt;
}
default: dflt: { /* it is a pattern item */
const char *ep = classend(ms, p); /* points to what is next */
@@ -418,20 +445,20 @@
case '?': { /* optional */
const char *res;
if (m && ((res=match(ms, s+1, ep+1)) != NULL))
- return res;
+ MATCH_RETURN(res);
p=ep+1; goto init; /* else return match(ms, s, ep+1); */
}
case '*': { /* 0 or more repetitions */
- return max_expand(ms, s, p, ep);
+ MATCH_RETURN(max_expand(ms, s, p, ep));
}
case '+': { /* 1 or more repetitions */
- return (m ? max_expand(ms, s+1, p, ep) : NULL);
+ MATCH_RETURN(m ? max_expand(ms, s+1, p, ep) : NULL);
}
case '-': { /* 0 or more repetitions (minimum) */
- return min_expand(ms, s, p, ep);
+ MATCH_RETURN(min_expand(ms, s, p, ep));
}
default: {
- if (!m) return NULL;
+ if (!m) MATCH_RETURN(NULL);
s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
}
}
@@ -439,7 +466,7 @@
}
}
-
+#undef MATCH_RETURN
static const char *lmemfind (const char *s1, size_t l1,
const char *s2, size_t l2) {
@@ -516,6 +543,7 @@
ms.L = L;
ms.src_init = s;
ms.src_end = s+l1;
+ ms.depth = 0;
do {
const char *res;
ms.level = 0;
@@ -554,6 +582,7 @@
ms.L = L;
ms.src_init = s;
ms.src_end = s+ls;
+ ms.depth = 0;
for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
src <= ms.src_end;
src++) {
@@ -658,6 +687,7 @@
ms.L = L;
ms.src_init = src;
ms.src_end = src+srcl;
+ ms.depth = 0;
while (n < max_s) {
const char *e;
ms.level = 0;
@@ -859,7 +889,7 @@
/*
** Open string library
*/
-LUALIB_API int luaopen_string (lua_State *L) {
+LUALIB_API int luasandbox_open_string (lua_State *L) {
luaL_register(L, LUA_STRLIBNAME, strlib);
#if defined(LUA_COMPAT_GFIND)
lua_getfield(L, -1, "gmatch");
|