Skip to content

Commit 1fc64c7

Browse files
committed
Limit number of imports during static validation
1 parent 9a3ec64 commit 1fc64c7

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ and this project adheres to
1717
### Changed
1818

1919
- cosmwasm-vm: Add checks for table section of Wasm blob ([#1631]).
20+
- cosmwasm-vm: Limit number of imports during static validation ([#1629]).
2021

22+
[#1629]: https://github.com/CosmWasm/cosmwasm/pull/1629
2123
[#1631]: https://github.com/CosmWasm/cosmwasm/pull/1631
2224

2325
## [1.2.3] - 2023-03-22

packages/vm/src/compatibility.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ const MEMORY_LIMIT: u32 = 512; // in pages
6464
/// is 485. Most are between 100 and 300.
6565
const TABLE_SIZE_LIMIT: u32 = 2500; // entries
6666

67+
/// If the contract has more than this amount of imports, it will be rejected
68+
/// during static validation before even looking into the imports. We keep this
69+
/// number high since failing early gives less detailed error messages. Especially
70+
/// when a user accidentally includes wasm-bindgen, they get a bunch of unsupported imports.
71+
const MAX_IMPORTS: usize = 100;
72+
6773
/// Checks if the data is valid wasm and compatibility with the CosmWasm API (imports and exports)
6874
pub fn check_wasm(wasm_code: &[u8], available_capabilities: &HashSet<String>) -> VmResult<()> {
6975
let module = deserialize_wasm(wasm_code)?;
@@ -195,6 +201,14 @@ fn check_wasm_imports(module: &Module, supported_imports: &[&str]) -> VmResult<(
195201
.import_section()
196202
.map_or(&[], |import_section| import_section.entries());
197203

204+
if required_imports.len() > MAX_IMPORTS {
205+
return Err(VmError::static_validation_err(format!(
206+
"Import count exceeds limit. Imports: {}. Limit: {}.",
207+
required_imports.len(),
208+
MAX_IMPORTS
209+
)));
210+
}
211+
198212
for required_import in required_imports {
199213
let full_name = full_import_name(required_import);
200214
if !supported_imports.contains(&full_name.as_str()) {
@@ -640,6 +654,124 @@ mod tests {
640654
check_wasm_imports(&deserialize_wasm(&wasm).unwrap(), SUPPORTED_IMPORTS).unwrap();
641655
}
642656

657+
#[test]
658+
fn check_wasm_imports_exceeds_limit() {
659+
let wasm = wat::parse_str(
660+
r#"(module
661+
(import "env" "db_write" (func (param i32 i32) (result i32)))
662+
(import "env" "db_remove" (func (param i32) (result i32)))
663+
(import "env" "addr_validate" (func (param i32) (result i32)))
664+
(import "env" "addr_canonicalize" (func (param i32 i32) (result i32)))
665+
(import "env" "addr_humanize" (func (param i32 i32) (result i32)))
666+
(import "env" "secp256k1_verify" (func (param i32 i32 i32) (result i32)))
667+
(import "env" "secp256k1_recover_pubkey" (func (param i32 i32 i32) (result i64)))
668+
(import "env" "ed25519_verify" (func (param i32 i32 i32) (result i32)))
669+
(import "env" "ed25519_batch_verify" (func (param i32 i32 i32) (result i32)))
670+
(import "env" "spam01" (func (param i32 i32) (result i32)))
671+
(import "env" "spam02" (func (param i32 i32) (result i32)))
672+
(import "env" "spam03" (func (param i32 i32) (result i32)))
673+
(import "env" "spam04" (func (param i32 i32) (result i32)))
674+
(import "env" "spam05" (func (param i32 i32) (result i32)))
675+
(import "env" "spam06" (func (param i32 i32) (result i32)))
676+
(import "env" "spam07" (func (param i32 i32) (result i32)))
677+
(import "env" "spam08" (func (param i32 i32) (result i32)))
678+
(import "env" "spam09" (func (param i32 i32) (result i32)))
679+
(import "env" "spam10" (func (param i32 i32) (result i32)))
680+
(import "env" "spam11" (func (param i32 i32) (result i32)))
681+
(import "env" "spam12" (func (param i32 i32) (result i32)))
682+
(import "env" "spam13" (func (param i32 i32) (result i32)))
683+
(import "env" "spam14" (func (param i32 i32) (result i32)))
684+
(import "env" "spam15" (func (param i32 i32) (result i32)))
685+
(import "env" "spam16" (func (param i32 i32) (result i32)))
686+
(import "env" "spam17" (func (param i32 i32) (result i32)))
687+
(import "env" "spam18" (func (param i32 i32) (result i32)))
688+
(import "env" "spam19" (func (param i32 i32) (result i32)))
689+
(import "env" "spam20" (func (param i32 i32) (result i32)))
690+
(import "env" "spam21" (func (param i32 i32) (result i32)))
691+
(import "env" "spam22" (func (param i32 i32) (result i32)))
692+
(import "env" "spam23" (func (param i32 i32) (result i32)))
693+
(import "env" "spam24" (func (param i32 i32) (result i32)))
694+
(import "env" "spam25" (func (param i32 i32) (result i32)))
695+
(import "env" "spam26" (func (param i32 i32) (result i32)))
696+
(import "env" "spam27" (func (param i32 i32) (result i32)))
697+
(import "env" "spam28" (func (param i32 i32) (result i32)))
698+
(import "env" "spam29" (func (param i32 i32) (result i32)))
699+
(import "env" "spam30" (func (param i32 i32) (result i32)))
700+
(import "env" "spam31" (func (param i32 i32) (result i32)))
701+
(import "env" "spam32" (func (param i32 i32) (result i32)))
702+
(import "env" "spam33" (func (param i32 i32) (result i32)))
703+
(import "env" "spam34" (func (param i32 i32) (result i32)))
704+
(import "env" "spam35" (func (param i32 i32) (result i32)))
705+
(import "env" "spam36" (func (param i32 i32) (result i32)))
706+
(import "env" "spam37" (func (param i32 i32) (result i32)))
707+
(import "env" "spam38" (func (param i32 i32) (result i32)))
708+
(import "env" "spam39" (func (param i32 i32) (result i32)))
709+
(import "env" "spam40" (func (param i32 i32) (result i32)))
710+
(import "env" "spam41" (func (param i32 i32) (result i32)))
711+
(import "env" "spam42" (func (param i32 i32) (result i32)))
712+
(import "env" "spam43" (func (param i32 i32) (result i32)))
713+
(import "env" "spam44" (func (param i32 i32) (result i32)))
714+
(import "env" "spam45" (func (param i32 i32) (result i32)))
715+
(import "env" "spam46" (func (param i32 i32) (result i32)))
716+
(import "env" "spam47" (func (param i32 i32) (result i32)))
717+
(import "env" "spam48" (func (param i32 i32) (result i32)))
718+
(import "env" "spam49" (func (param i32 i32) (result i32)))
719+
(import "env" "spam50" (func (param i32 i32) (result i32)))
720+
(import "env" "spam51" (func (param i32 i32) (result i32)))
721+
(import "env" "spam52" (func (param i32 i32) (result i32)))
722+
(import "env" "spam53" (func (param i32 i32) (result i32)))
723+
(import "env" "spam54" (func (param i32 i32) (result i32)))
724+
(import "env" "spam55" (func (param i32 i32) (result i32)))
725+
(import "env" "spam56" (func (param i32 i32) (result i32)))
726+
(import "env" "spam57" (func (param i32 i32) (result i32)))
727+
(import "env" "spam58" (func (param i32 i32) (result i32)))
728+
(import "env" "spam59" (func (param i32 i32) (result i32)))
729+
(import "env" "spam60" (func (param i32 i32) (result i32)))
730+
(import "env" "spam61" (func (param i32 i32) (result i32)))
731+
(import "env" "spam62" (func (param i32 i32) (result i32)))
732+
(import "env" "spam63" (func (param i32 i32) (result i32)))
733+
(import "env" "spam64" (func (param i32 i32) (result i32)))
734+
(import "env" "spam65" (func (param i32 i32) (result i32)))
735+
(import "env" "spam66" (func (param i32 i32) (result i32)))
736+
(import "env" "spam67" (func (param i32 i32) (result i32)))
737+
(import "env" "spam68" (func (param i32 i32) (result i32)))
738+
(import "env" "spam69" (func (param i32 i32) (result i32)))
739+
(import "env" "spam70" (func (param i32 i32) (result i32)))
740+
(import "env" "spam71" (func (param i32 i32) (result i32)))
741+
(import "env" "spam72" (func (param i32 i32) (result i32)))
742+
(import "env" "spam73" (func (param i32 i32) (result i32)))
743+
(import "env" "spam74" (func (param i32 i32) (result i32)))
744+
(import "env" "spam75" (func (param i32 i32) (result i32)))
745+
(import "env" "spam76" (func (param i32 i32) (result i32)))
746+
(import "env" "spam77" (func (param i32 i32) (result i32)))
747+
(import "env" "spam78" (func (param i32 i32) (result i32)))
748+
(import "env" "spam79" (func (param i32 i32) (result i32)))
749+
(import "env" "spam80" (func (param i32 i32) (result i32)))
750+
(import "env" "spam81" (func (param i32 i32) (result i32)))
751+
(import "env" "spam82" (func (param i32 i32) (result i32)))
752+
(import "env" "spam83" (func (param i32 i32) (result i32)))
753+
(import "env" "spam84" (func (param i32 i32) (result i32)))
754+
(import "env" "spam85" (func (param i32 i32) (result i32)))
755+
(import "env" "spam86" (func (param i32 i32) (result i32)))
756+
(import "env" "spam87" (func (param i32 i32) (result i32)))
757+
(import "env" "spam88" (func (param i32 i32) (result i32)))
758+
(import "env" "spam89" (func (param i32 i32) (result i32)))
759+
(import "env" "spam90" (func (param i32 i32) (result i32)))
760+
(import "env" "spam91" (func (param i32 i32) (result i32)))
761+
(import "env" "spam92" (func (param i32 i32) (result i32)))
762+
)"#,
763+
)
764+
.unwrap();
765+
let err =
766+
check_wasm_imports(&deserialize_wasm(&wasm).unwrap(), SUPPORTED_IMPORTS).unwrap_err();
767+
match err {
768+
VmError::StaticValidationErr { msg, .. } => {
769+
assert_eq!(msg, "Import count exceeds limit. Imports: 101. Limit: 100.");
770+
}
771+
err => panic!("Unexpected error: {:?}", err),
772+
}
773+
}
774+
643775
#[test]
644776
fn check_wasm_imports_missing() {
645777
let wasm = wat::parse_str(

0 commit comments

Comments
 (0)