Skip to content

Commit

Permalink
adds state-specific execution limit overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
Y0SH1M4S73R committed Nov 3, 2024
1 parent 79193e2 commit 600cff3
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
37 changes: 34 additions & 3 deletions dmsrc/api.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


/**
* Sets the execution limit, in milliseconds.
* Sets the global execution limit, in milliseconds.
*
* @param limit the new execution limit
*
Expand All @@ -28,7 +28,7 @@
#define DREAMLUAU_SET_EXECUTION_LIMIT_MILLIS(limit) DREAMLUAU_CALL(set_execution_limit_millis)((limit))

/**
* Sets the execution limit, in seconds.
* Sets the global execution limit, in seconds.
*
* @param limit the new execution limit
*
Expand All @@ -37,7 +37,7 @@
#define DREAMLUAU_SET_EXECUTION_LIMIT_SECS(limit) DREAMLUAU_CALL(set_execution_limit_secs)((limit))

/**
* Clears the execution limit, allowing scripts to run as long as they need to.
* Clears the global execution limit, allowing scripts to run as long as they need to.
*
* WARNING: This allows infinite loops to block Dream Daemon indefinitely, with no safety checks.
* Do not use this if you have no reason for scripts to run arbitrarily long.
Expand Down Expand Up @@ -299,5 +299,36 @@
*/
#define DREAMLUAU_CLEAR_REF_USERDATA(object) DREAMLUAU_CALL(clear_ref_userdata)((object))

/**
* Sets a state's execution limit override, in milliseconds.
*
* @param state the handle to the state
*
* @param limit the new execution limit
*
* @return null on success
*/
#define DREAMLUAU_SET_EXECUTION_LIMIT_MILLIS(state, limit) DREAMLUAU_CALL(set_execution_limit_millis)((state), (limit))

/**
* Sets a state's execution limit override, in seconds.
*
* @param state the handle to the state
*
* @param limit the new execution limit
*
* @return null on success
*/
#define DREAMLUAU_SET_EXECUTION_LIMIT_SECS(state, limit) DREAMLUAU_CALL(set_execution_limit_secs)((state), (limit))

/**
* Clears a state's execution limit override, returning control of its execution to the global limit.
*
* @param state the handle to the state
*
* @return null on success
*/
#define DREAMLUAU_CLEAR_EXECUTION_LIMIT(state) DREAMLUAU_CALL(clear_execution_limit)((state))

/proc/_hascall(object, procname)
return hascall(object, procname)
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ mod value;
pub(crate) mod wrappers;

pub use state::{
awaken, call_function, clear_execution_limit, clear_ref_userdata, collect_garbage, get_globals,
get_traceback, is_isolated, kill_sleeping_thread, kill_state, kill_yielded_thread,
list_threads, load, new_state, resume, set_execution_limit_millis, set_execution_limit_secs,
awaken, call_function, clear_execution_limit, clear_ref_userdata, clear_state_execution_limit,
collect_garbage, get_globals, get_traceback, is_isolated, kill_sleeping_thread, kill_state,
kill_yielded_thread, list_threads, load, new_state, resume, set_execution_limit_millis,
set_execution_limit_secs, set_state_execution_limit_millis, set_state_execution_limit_secs,
set_usr,
};

Expand Down
12 changes: 9 additions & 3 deletions src/state/exec_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,16 @@ pub fn set_privileged_execution(privileged: bool) {
}

#[map_statics(EXECUTION_START, EXECUTION_LIMIT, PRIVILEGED_EXECUTION)]
pub fn limiting_interrupt(_: &Lua) -> LuaResult<VmState> {
match (execution_limit, execution_start, privileged_execution) {
pub fn limiting_interrupt(lua: &Lua) -> LuaResult<VmState> {
match (
lua.named_registry_value::<Option<f32>>("exec_limit")?
.map(Duration::from_secs_f32)
.or(*execution_limit),
execution_start,
privileged_execution,
) {
(_, _, true) => Ok(VmState::Continue),
(Some(limit), Some(start), _) => (start.elapsed() <= *limit)
(Some(limit), Some(start), _) => (start.elapsed() <= limit)
.then_some(VmState::Continue)
.ok_or_else(|| {
LuaError::external(
Expand Down
27 changes: 27 additions & 0 deletions src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,30 @@ pub fn clear_ref_userdata(value: ByondValue) -> ByondResult<()> {
.try_for_each(|lua| drop_cached_userdata(&Value(value.clone()), lua))
.map_err(ByondError::boxed)
}

#[byond_fn]
pub fn set_state_execution_limit_millis(index: usize, new_limit: u32) -> ByondResult<()> {
get_state(index).and_then(|state| {
state
.set_named_registry_value("exec_limit", new_limit as f32 * 1000.0)
.map_err(ByondError::boxed)
})
}

#[byond_fn]
pub fn set_state_execution_limit_secs(index: usize, new_limit: f32) -> ByondResult<()> {
get_state(index).and_then(|state| {
state
.set_named_registry_value("exec_limit", new_limit)
.map_err(ByondError::boxed)
})
}

#[byond_fn]
pub fn clear_state_execution_limit(index: usize) -> ByondResult<()> {
get_state(index).and_then(|state| {
state
.unset_named_registry_value("exec_limit")
.map_err(ByondError::boxed)
})
}

0 comments on commit 600cff3

Please sign in to comment.