Browse Source

Limit depth of mg.include for Lua server pages

bel 8 years ago
parent
commit
60dc35a486
2 changed files with 37 additions and 4 deletions
  1. 1 1
      RELEASE_NOTES.md
  2. 36 3
      src/mod_lua.inl

+ 1 - 1
RELEASE_NOTES.md

@@ -5,7 +5,7 @@ Release Notes v1.10 (work in progress)
 Changes
 -------
 
-
+- Limit depth of mg.include for Lua server pages
 - Additional unit tests
 - OpenSSL 1.1 support
 - Update version number

+ 36 - 3
src/mod_lua.inl

@@ -48,6 +48,12 @@ munmap(void *addr, int64_t length)
 static const char *LUASOCKET = "luasocket";
 static const char lua_regkey_ctx = 1;
 static const char lua_regkey_connlist = 2;
+static const char lua_regkey_lsp_include_depth = 3;
+
+#ifndef LSP_INCLUDE_MAX_DEPTH
+#define LSP_INCLUDE_MAX_DEPTH (32)
+#endif
+
 
 /* Forward declarations */
 static void handle_request(struct mg_connection *);
@@ -531,13 +537,32 @@ lsp_include(lua_State *L)
 	const char *filename = (num_args == 1) ? lua_tostring(L, 1) : NULL;
 
 	if (filename) {
-		if (handle_lsp_request(conn, filename, &file, L)) {
+		int depth;
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_depth);
+		lua_gettable(L, LUA_REGISTRYINDEX);
+		depth = lua_tointeger(L, -1);
+
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_depth);
+		lua_pushinteger(L, depth + 1);
+		lua_settable(L, LUA_REGISTRYINDEX);
+
+		if (depth >= ((int)(LSP_INCLUDE_MAX_DEPTH))) {
+			mg_cry(conn,
+			       "lsp max include depth of %i reached while including %s",
+			       (int)(LSP_INCLUDE_MAX_DEPTH),
+			       filename);
+		} else if (handle_lsp_request(conn, filename, &file, L)) {
 			/* handle_lsp_request returned an error code, meaning an error
-			occured in
-			the included page and mg.onerror returned non-zero. Stop processing.
+			* occured in the included page and mg.onerror returned non-zero.
+			* Stop processing.
 			*/
 			lsp_abort(L);
 		}
+
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_depth);
+		lua_pushinteger(L, depth);
+		lua_settable(L, LUA_REGISTRYINDEX);
+
 	} else {
 		/* Syntax error */
 		return luaL_error(L, "invalid include() call");
@@ -1384,6 +1409,14 @@ prepare_lua_environment(struct mg_context *ctx,
 		lua_settable(L, LUA_REGISTRYINDEX);
 	}
 
+	/* Lua server pages store the depth of mg.include, in order
+	 * to detect recursions and prevent stack overflows. */
+	if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE) {
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_depth);
+		lua_pushinteger(L, 0);
+		lua_settable(L, LUA_REGISTRYINDEX);
+	}
+
 	/* Register mg module */
 	lua_newtable(L);