From 7230657f6f4d8ce5efee291f171ca45782d8c3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Lecomte?= Date: Tue, 25 Nov 2025 18:11:25 +0100 Subject: [PATCH] feat: expose building a CompiledPlugin with a fuel limit (#883) Expose a new method `extism_compiled_plugin_new_with_fuel_limit` to build a CompiledPlugin with a fuel limit. Fixes #882 --- runtime/extism.h | 11 ++++++++ runtime/src/sdk.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/runtime/extism.h b/runtime/extism.h index b029bed..ec798b7 100644 --- a/runtime/extism.h +++ b/runtime/extism.h @@ -191,6 +191,17 @@ ExtismCompiledPlugin *extism_compiled_plugin_new(const uint8_t *wasm, bool with_wasi, char **errmsg); +/** + * Pre-compile an Extism plugin and set the number of instructions a plugin is allowed to execute + */ +ExtismCompiledPlugin *extism_compiled_plugin_new_with_fuel_limit(const uint8_t *wasm, + ExtismSize wasm_size, + const ExtismFunction **functions, + ExtismSize n_functions, + bool with_wasi, + uint64_t fuel_limit, + char **errmsg); + /** * Free `ExtismCompiledPlugin` */ diff --git a/runtime/src/sdk.rs b/runtime/src/sdk.rs index 9abd110..752721d 100644 --- a/runtime/src/sdk.rs +++ b/runtime/src/sdk.rs @@ -363,6 +363,70 @@ pub unsafe extern "C" fn extism_compiled_plugin_new( }) } +/// Pre-compile an Extism plugin and set the number of instructions a plugin is allowed to execute +#[no_mangle] +pub unsafe extern "C" fn extism_compiled_plugin_new_with_fuel_limit( + wasm: *const u8, + wasm_size: Size, + functions: *mut *const ExtismFunction, + n_functions: Size, + with_wasi: bool, + fuel_limit: u64, + errmsg: *mut *mut std::ffi::c_char, +) -> *mut CompiledPlugin { + trace!("Call to extism_plugin_new with wasm pointer {:?}", wasm); + let data = std::slice::from_raw_parts(wasm, wasm_size as usize); + + let mut builder = PluginBuilder::new(data) + .with_wasi(with_wasi) + .with_fuel_limit(fuel_limit); + + if !functions.is_null() { + let funcs = (0..n_functions) + .map(|i| unsafe { *functions.add(i as usize) }) + .map(|ptr| { + if ptr.is_null() { + return Err("Cannot pass null pointer"); + } + + let ExtismFunction(func) = &*ptr; + let Some(func) = func.take() else { + return Err("Function cannot be registered with multiple different Plugins"); + }; + + Ok(func) + }) + .collect::, _>>() + .unwrap_or_else(|e| { + if !errmsg.is_null() { + let e = std::ffi::CString::new(e.to_string()).unwrap(); + *errmsg = e.into_raw(); + } + Vec::new() + }); + + if funcs.len() != n_functions as usize { + return std::ptr::null_mut(); + } + + builder = builder.with_functions(funcs); + } + + CompiledPlugin::new(builder) + .map(|v| Box::into_raw(Box::new(v))) + .unwrap_or_else(|e| { + if !errmsg.is_null() { + let e = std::ffi::CString::new(format!( + "Unable to compile Extism plugin: {}", + e.root_cause(), + )) + .unwrap(); + *errmsg = e.into_raw(); + } + std::ptr::null_mut() + }) +} + /// Free `ExtismCompiledPlugin` #[no_mangle] pub unsafe extern "C" fn extism_compiled_plugin_free(plugin: *mut CompiledPlugin) {