Skip to content
This repository was archived by the owner on Dec 29, 2024. It is now read-only.

Commit 63e8aa0

Browse files
authored
Add max memory usage restrictions (#147)
1 parent 48105a6 commit 63e8aa0

File tree

3 files changed

+85
-11
lines changed

3 files changed

+85
-11
lines changed

doc_classes/LuaAPI.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,21 @@
104104
<description>
105105
Controls the garbage collector. The option can be one of the following: [code]GC_STOP[/code], [code]GC_RESTART[/code], [code]GC_COLLECT[/code], [code]GC_COUNT[/code], [code]GC_STEP[/code], [code]GC_SETPAUSE[/code], [code]GC_SETSTEPMUL[/code]. The data is the argument for the option. Returns the result of the option.
106106
</description>
107+
</method>
108+
<method name="get_memory_usage">
109+
<return type="int" />
110+
<description>
111+
Returns the current memory usage of the state in bytes.
112+
</description>
113+
</method>
107114
</methods>
108115
<members>
109116
<member name="permissive" type="bool" setter="set_permissive" getter="get_permissive" default="true">
110117
When set to true all methods will be allowed on Objects be default and lua_fields is treated as a blacklist. When set to false, lua_fields is treated as a whitelist.
111118
</member>
119+
<member name="memory_limit" type="int" setter="set_memory_limit" getter="get_memory_limit" default="0">
120+
Sets the memory limit for the state in bytes. If the limit is 0, there is no limit.
121+
</member>
112122
</members>
113123
<constants>
114124
<constant name="GC_STOP" value="1" enum="HookMask">

src/classes/luaAPI.cpp

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#endif
1010

1111
LuaAPI::LuaAPI() {
12-
lState = luaL_newstate();
12+
lState = lua_newstate(&LuaAPI::luaAlloc, (void *)&luaAllocData);
13+
1314
// Creating lua state instance
1415
state.setState(lState, this, true);
1516
}
@@ -25,7 +26,8 @@ void LuaAPI::_bind_methods() {
2526

2627
ClassDB::bind_method(D_METHOD("bind_libraries", "Array"), &LuaAPI::bindLibraries);
2728
ClassDB::bind_method(D_METHOD("set_hook", "Hook", "HookMask", "Count"), &LuaAPI::setHook);
28-
ClassDB::bind_method(D_METHOD("configure_gc", "What", "Data"), &LuaAPI::configure_gc);
29+
ClassDB::bind_method(D_METHOD("configure_gc", "What", "Data"), &LuaAPI::configureGC);
30+
ClassDB::bind_method(D_METHOD("get_memory_usage"), &LuaAPI::getMemoryUsage);
2931
ClassDB::bind_method(D_METHOD("push_variant", "Name", "var"), &LuaAPI::pushGlobalVariant);
3032
ClassDB::bind_method(D_METHOD("pull_variant", "Name"), &LuaAPI::pullVariant);
3133
ClassDB::bind_method(D_METHOD("expose_constructor", "LuaConstructorName", "Object"), &LuaAPI::exposeObjectConstructor);
@@ -39,7 +41,11 @@ void LuaAPI::_bind_methods() {
3941
ClassDB::bind_method(D_METHOD("set_permissive", "value"), &LuaAPI::setPermissive);
4042
ClassDB::bind_method(D_METHOD("get_permissive"), &LuaAPI::getPermissive);
4143

44+
ClassDB::bind_method(D_METHOD("set_memory_limit", "limit"), &LuaAPI::setMemoryLimit);
45+
ClassDB::bind_method(D_METHOD("get_memory_limit"), &LuaAPI::getMemoryLimit);
46+
4247
ADD_PROPERTY(PropertyInfo(Variant::INT, "permissive"), "set_permissive", "get_permissive");
48+
ADD_PROPERTY(PropertyInfo(Variant::INT, "memory_limit"), "set_memory_limit", "get_memory_limit");
4349

4450
BIND_ENUM_CONSTANT(HOOK_MASK_CALL);
4551
BIND_ENUM_CONSTANT(HOOK_MASK_RETURN);
@@ -65,6 +71,30 @@ void LuaAPI::setHook(Callable hook, int mask, int count) {
6571
return state.setHook(hook, mask, count);
6672
}
6773

74+
int LuaAPI::configureGC(int what, int data) {
75+
return lua_gc(lState, what, data);
76+
}
77+
78+
void LuaAPI::setPermissive(bool value) {
79+
permissive = value;
80+
}
81+
82+
bool LuaAPI::getPermissive() const {
83+
return permissive;
84+
}
85+
86+
void LuaAPI::setMemoryLimit(int limit) {
87+
luaAllocData.memoryLimit = limit;
88+
}
89+
90+
int LuaAPI::getMemoryLimit() const {
91+
return luaAllocData.memoryLimit;
92+
}
93+
94+
int LuaAPI::getMemoryUsage() const {
95+
return luaAllocData.memoryUsed;
96+
}
97+
6898
// Calls LuaState::luaFunctionExists()
6999
bool LuaAPI::luaFunctionExists(String functionName) {
70100
return state.luaFunctionExists(functionName);
@@ -204,3 +234,31 @@ lua_State *LuaAPI::newThreadState() {
204234
lua_State *LuaAPI::getState() {
205235
return lState;
206236
}
237+
238+
void *LuaAPI::luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize) {
239+
LuaAllocData *data = (LuaAllocData *)ud;
240+
if (nsize == 0) {
241+
if (ptr != nullptr) {
242+
data->memoryUsed -= osize;
243+
memfree(ptr);
244+
}
245+
return nullptr;
246+
}
247+
248+
if (ptr == nullptr) {
249+
if (data->memoryLimit != 0 && data->memoryUsed + nsize > data->memoryLimit) {
250+
return nullptr;
251+
}
252+
253+
data->memoryUsed += nsize;
254+
return memalloc(nsize);
255+
}
256+
257+
if (data->memoryLimit != 0 && data->memoryUsed - osize + nsize > data->memoryLimit) {
258+
return nullptr;
259+
}
260+
261+
data->memoryUsed -= osize;
262+
data->memoryUsed += nsize;
263+
return memrealloc(ptr, nsize);
264+
}

src/classes/luaAPI.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,14 @@ class LuaAPI : public RefCounted {
3232
void bindLibraries(Array libs);
3333
void setHook(Callable hook, int mask, int count);
3434

35-
inline int configure_gc(int what, int data) {
36-
return lua_gc(lState, what, data);
37-
}
35+
void setPermissive(bool value);
36+
bool getPermissive() const;
3837

39-
inline void setPermissive(bool value) {
40-
permissive = value;
41-
}
38+
void setMemoryLimit(int limit);
39+
int getMemoryLimit() const;
4240

43-
inline bool getPermissive() const {
44-
return permissive;
45-
}
41+
int configureGC(int what, int data);
42+
int getMemoryUsage() const;
4643

4744
bool luaFunctionExists(String functionName);
4845

@@ -83,6 +80,15 @@ class LuaAPI : public RefCounted {
8380
LuaState state;
8481
lua_State *lState = nullptr;
8582

83+
static void *luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize);
84+
85+
struct LuaAllocData {
86+
int memoryUsed = 0;
87+
int memoryLimit = 0;
88+
};
89+
90+
LuaAllocData luaAllocData;
91+
8692
bool permissive = true;
8793

8894
LuaError *execute(int handlerIndex);

0 commit comments

Comments
 (0)