@@ -34,6 +34,12 @@ pub const DEFAULT_MAX_TABLE_ELEMENTS: usize = 10_000;
3434pub const DEFAULT_FUEL : u64 = 5_000_000 ;
3535pub const DEFAULT_TIMEOUT : Duration = Duration :: from_millis ( 50 ) ;
3636pub const DEFAULT_COMPILE_TIMEOUT : Duration = Duration :: from_millis ( 500 ) ;
37+ pub const HARD_MAX_MODULE_BYTES : u64 = 16 * 1024 * 1024 ;
38+ pub const HARD_MAX_MEMORY_BYTES : usize = 256 * 1024 * 1024 ;
39+ pub const HARD_MAX_TABLE_ELEMENTS : usize = 100_000 ;
40+ pub const HARD_MAX_FUEL : u64 = 100_000_000 ;
41+ pub const HARD_MAX_TIMEOUT : Duration = Duration :: from_secs ( 5 ) ;
42+ pub const HARD_MAX_COMPILE_TIMEOUT : Duration = Duration :: from_secs ( 10 ) ;
3743
3844#[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
3945pub struct WasmSandboxLimits {
@@ -60,40 +66,40 @@ impl Default for WasmSandboxLimits {
6066
6167impl WasmSandboxLimits {
6268 pub fn validate ( self ) -> Result < Self , WasmPluginError > {
63- if self . max_module_bytes == 0 {
69+ if self . max_module_bytes == 0 || self . max_module_bytes > HARD_MAX_MODULE_BYTES {
6470 return Err ( WasmPluginError :: InvalidLimit {
6571 field : "max_module_bytes" ,
66- reason : "must be greater than zero " ,
72+ reason : "must be between 1 byte and 16 MiB " ,
6773 } ) ;
6874 }
69- if self . max_memory_bytes == 0 {
75+ if self . max_memory_bytes == 0 || self . max_memory_bytes > HARD_MAX_MEMORY_BYTES {
7076 return Err ( WasmPluginError :: InvalidLimit {
7177 field : "max_memory_bytes" ,
72- reason : "must be greater than zero " ,
78+ reason : "must be between 1 byte and 256 MiB " ,
7379 } ) ;
7480 }
75- if self . max_table_elements == 0 {
81+ if self . max_table_elements == 0 || self . max_table_elements > HARD_MAX_TABLE_ELEMENTS {
7682 return Err ( WasmPluginError :: InvalidLimit {
7783 field : "max_table_elements" ,
78- reason : "must be greater than zero " ,
84+ reason : "must be between 1 and 100000 " ,
7985 } ) ;
8086 }
81- if self . fuel == 0 {
87+ if self . fuel == 0 || self . fuel > HARD_MAX_FUEL {
8288 return Err ( WasmPluginError :: InvalidLimit {
8389 field : "fuel" ,
84- reason : "must be greater than zero " ,
90+ reason : "must be between 1 and 100000000 " ,
8591 } ) ;
8692 }
87- if self . timeout . is_zero ( ) {
93+ if self . timeout . is_zero ( ) || self . timeout > HARD_MAX_TIMEOUT {
8894 return Err ( WasmPluginError :: InvalidLimit {
8995 field : "timeout" ,
90- reason : "must be greater than zero " ,
96+ reason : "must be between 1ns and 5s " ,
9197 } ) ;
9298 }
93- if self . compile_timeout . is_zero ( ) {
99+ if self . compile_timeout . is_zero ( ) || self . compile_timeout > HARD_MAX_COMPILE_TIMEOUT {
94100 return Err ( WasmPluginError :: InvalidLimit {
95101 field : "compile_timeout" ,
96- reason : "must be greater than zero " ,
102+ reason : "must be between 1ns and 10s " ,
97103 } ) ;
98104 }
99105 Ok ( self )
@@ -121,4 +127,78 @@ mod tests {
121127 }
122128 ) ) ;
123129 }
130+
131+ #[ test]
132+ fn sandbox_limits_reject_values_above_hard_ceiling ( ) {
133+ let cases = [
134+ (
135+ "max_module_bytes" ,
136+ WasmSandboxLimits {
137+ max_module_bytes : HARD_MAX_MODULE_BYTES + 1 ,
138+ ..WasmSandboxLimits :: default ( )
139+ } ,
140+ ) ,
141+ (
142+ "max_memory_bytes" ,
143+ WasmSandboxLimits {
144+ max_memory_bytes : HARD_MAX_MEMORY_BYTES + 1 ,
145+ ..WasmSandboxLimits :: default ( )
146+ } ,
147+ ) ,
148+ (
149+ "max_table_elements" ,
150+ WasmSandboxLimits {
151+ max_table_elements : HARD_MAX_TABLE_ELEMENTS + 1 ,
152+ ..WasmSandboxLimits :: default ( )
153+ } ,
154+ ) ,
155+ (
156+ "fuel" ,
157+ WasmSandboxLimits {
158+ fuel : HARD_MAX_FUEL + 1 ,
159+ ..WasmSandboxLimits :: default ( )
160+ } ,
161+ ) ,
162+ (
163+ "timeout" ,
164+ WasmSandboxLimits {
165+ timeout : HARD_MAX_TIMEOUT + Duration :: from_nanos ( 1 ) ,
166+ ..WasmSandboxLimits :: default ( )
167+ } ,
168+ ) ,
169+ (
170+ "compile_timeout" ,
171+ WasmSandboxLimits {
172+ compile_timeout : HARD_MAX_COMPILE_TIMEOUT + Duration :: from_nanos ( 1 ) ,
173+ ..WasmSandboxLimits :: default ( )
174+ } ,
175+ ) ,
176+ ] ;
177+
178+ for ( field, limits) in cases {
179+ assert ! ( matches!(
180+ limits. validate( ) ,
181+ Err ( WasmPluginError :: InvalidLimit {
182+ field: invalid,
183+ ..
184+ } ) if invalid == field
185+ ) ) ;
186+ }
187+ }
188+
189+ #[ test]
190+ fn sandbox_limits_accept_values_at_hard_ceiling ( ) {
191+ assert ! (
192+ WasmSandboxLimits {
193+ max_module_bytes: HARD_MAX_MODULE_BYTES ,
194+ max_memory_bytes: HARD_MAX_MEMORY_BYTES ,
195+ max_table_elements: HARD_MAX_TABLE_ELEMENTS ,
196+ fuel: HARD_MAX_FUEL ,
197+ timeout: HARD_MAX_TIMEOUT ,
198+ compile_timeout: HARD_MAX_COMPILE_TIMEOUT ,
199+ }
200+ . validate( )
201+ . is_ok( )
202+ ) ;
203+ }
124204}
0 commit comments