mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-08 13:38:11 +00:00
srml-contract: Validate that modules do not declare oversized tables. (#2969)
* srml-contract: Validate that modules do not declare oversized tables. * Bump node runtime spec/impl versions.
This commit is contained in:
@@ -66,8 +66,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
// Per convention: if the runtime behavior changes, increment spec_version and set impl_version
|
||||
// to equal spec_version. If only runtime implementation changes and behavior does not, then
|
||||
// leave spec_version as is and increment impl_version.
|
||||
spec_version: 101,
|
||||
impl_version: 101,
|
||||
spec_version: 102,
|
||||
impl_version: 102,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
@@ -886,6 +886,9 @@ pub struct Schedule {
|
||||
/// Maximum number of memory pages allowed for a contract.
|
||||
pub max_memory_pages: u32,
|
||||
|
||||
/// Maximum allowed size of a declared table.
|
||||
pub max_table_size: u32,
|
||||
|
||||
/// Whether the `ext_println` function is allowed to be used contracts.
|
||||
/// MUST only be enabled for `dev` chains, NOT for production chains
|
||||
pub enable_println: bool,
|
||||
@@ -912,6 +915,7 @@ impl Default for Schedule {
|
||||
max_event_topics: 4,
|
||||
max_stack_height: 64 * 1024,
|
||||
max_memory_pages: 16,
|
||||
max_table_size: 16 * 1024,
|
||||
enable_println: false,
|
||||
max_subject_len: 32,
|
||||
}
|
||||
|
||||
@@ -74,6 +74,25 @@ impl<'a> ContractModule<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ensures that tables declared in the module are not too big.
|
||||
fn ensure_table_size_limit(&self, limit: u32) -> Result<(), &'static str> {
|
||||
if let Some(table_section) = self.module.table_section() {
|
||||
// In Wasm MVP spec, there may be at most one table declared. Double check this
|
||||
// explicitly just in case the Wasm version changes.
|
||||
if table_section.entries().len() > 1 {
|
||||
return Err("multiple tables declared");
|
||||
}
|
||||
if let Some(table_type) = table_section.entries().first() {
|
||||
// Check the table's initial size as there is no instruction or environment function
|
||||
// capable of growing the table.
|
||||
if table_type.limits().initial() > limit {
|
||||
return Err("table exceeds maximum size allowed")
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inject_gas_metering(self) -> Result<Self, &'static str> {
|
||||
let gas_rules =
|
||||
rules::Set::new(
|
||||
@@ -271,6 +290,7 @@ pub fn prepare_contract<C: ImportSatisfyCheck>(
|
||||
let mut contract_module = ContractModule::new(original_code, schedule)?;
|
||||
contract_module.scan_exports()?;
|
||||
contract_module.ensure_no_internal_memory()?;
|
||||
contract_module.ensure_table_size_limit(schedule.max_table_size)?;
|
||||
|
||||
struct MemoryDefinition {
|
||||
initial: u32,
|
||||
@@ -503,6 +523,49 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
mod tables {
|
||||
use super::*;
|
||||
|
||||
// Tests below assumes that maximum table size is configured to a certain number.
|
||||
#[test]
|
||||
fn assume_table_size() {
|
||||
assert_eq!(Schedule::default().max_table_size, 16384);
|
||||
}
|
||||
|
||||
prepare_test!(no_tables,
|
||||
r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#,
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(table_valid_size,
|
||||
r#"
|
||||
(module
|
||||
(table 10000 funcref)
|
||||
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#,
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
prepare_test!(table_too_big,
|
||||
r#"
|
||||
(module
|
||||
(table 20000 funcref)
|
||||
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)"#,
|
||||
Err("table exceeds maximum size allowed")
|
||||
);
|
||||
}
|
||||
|
||||
mod imports {
|
||||
use super::*;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user