Skip to content

Commit 9d5bfef

Browse files
authored
Merge pull request #2344 from CosmWasm/aw/memory-safety-doc
Add safety documentation
2 parents c365711 + 56d9d29 commit 9d5bfef

File tree

4 files changed

+137
-69
lines changed

4 files changed

+137
-69
lines changed

CHANGELOG.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,29 @@ and this project adheres to
1313
- cosmwasm-std: Implement `From<Uint64> for u{64,128}`,
1414
`From<Uint128> for u128`, `From<Int64> for i{64,128}`, and
1515
`From<Int128> for i128` ([#2268])
16-
- cosmwasm-std: Deprecate `abort` feature. The panic handler is now always
17-
enabled. ([#2337])
1816
- cosmwasm-std: Implement `Uint128::from_{be,le}_bytes` and
1917
`Uint64::from_{be,le}_bytes`. ([#2269])
18+
- cosmwasm-std: Added new `EurekaMsg` and `CosmosMsg::Eureka` variant ([#2340])
2019

21-
[#2268]: https://github.com/CosmWasm/cosmwasm/issues/2268
22-
[#2337]: https://github.com/CosmWasm/cosmwasm/issues/2337
23-
[#2269]: https://github.com/CosmWasm/cosmwasm/issues/2269
20+
## Changed
21+
22+
- cosmwasm-std: Deprecate `abort` feature. The panic handler is now always
23+
enabled. ([#2337])
24+
- cosmwasm-std: Document safety invariants of the internal memory repr ([#2344])
25+
- cosmwasm-std: Enforce non-null pointers using `ptr::NonNull` in the internal
26+
memory repr ([#2344])
2427

2528
## Fixed
2629

2730
- cosmwasm-schema: The schema export now doesn't overwrite existing
2831
`additionalProperties` values anymore ([#2310])
29-
- cosmwasm-std: Added new `EurekaMsg` and `CosmosMsg::Eureka` variant ([#2340])
3032

33+
[#2268]: https://github.com/CosmWasm/cosmwasm/issues/2268
34+
[#2269]: https://github.com/CosmWasm/cosmwasm/issues/2269
3135
[#2310]: https://github.com/CosmWasm/cosmwasm/pull/2310
36+
[#2337]: https://github.com/CosmWasm/cosmwasm/issues/2337
3237
[#2340]: https://github.com/CosmWasm/cosmwasm/pull/2340
38+
[#2344]: https://github.com/CosmWasm/cosmwasm/pull/2344
3339

3440
## [2.2.0] - 2024-12-17
3541

packages/std/src/exports.rs

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! the contract-specific function pointer. This is done via the `#[entry_point]`
99
//! macro attribute from cosmwasm-derive.
1010
use alloc::vec::Vec;
11-
use core::marker::PhantomData;
11+
use core::{marker::PhantomData, ptr};
1212

1313
use serde::de::DeserializeOwned;
1414

@@ -95,7 +95,8 @@ extern "C" fn allocate(size: usize) -> u32 {
9595
#[no_mangle]
9696
extern "C" fn deallocate(pointer: u32) {
9797
// auto-drop Region on function end
98-
let _ = unsafe { Region::from_heap_ptr(pointer as *mut Region<Owned>) };
98+
let _ =
99+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(pointer as *mut Region<Owned>).unwrap()) };
99100
}
100101

101102
// TODO: replace with https://doc.rust-lang.org/std/ops/trait.Try.html once stabilized
@@ -533,9 +534,12 @@ where
533534
C: CustomMsg,
534535
E: ToString,
535536
{
536-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
537-
let info: Vec<u8> = unsafe { Region::from_heap_ptr(info_ptr).into_vec() };
538-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
537+
let env: Vec<u8> =
538+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
539+
let info: Vec<u8> =
540+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(info_ptr).unwrap()).into_vec() };
541+
let msg: Vec<u8> =
542+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
539543

540544
let env: Env = try_into_contract_result!(from_json(env));
541545
let info: MessageInfo = try_into_contract_result!(from_json(info));
@@ -557,9 +561,12 @@ where
557561
C: CustomMsg,
558562
E: ToString,
559563
{
560-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
561-
let info: Vec<u8> = unsafe { Region::from_heap_ptr(info_ptr).into_vec() };
562-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
564+
let env: Vec<u8> =
565+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
566+
let info: Vec<u8> =
567+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(info_ptr).unwrap()).into_vec() };
568+
let msg: Vec<u8> =
569+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
563570

564571
let env: Env = try_into_contract_result!(from_json(env));
565572
let info: MessageInfo = try_into_contract_result!(from_json(info));
@@ -580,8 +587,10 @@ where
580587
C: CustomMsg,
581588
E: ToString,
582589
{
583-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
584-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
590+
let env: Vec<u8> =
591+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
592+
let msg: Vec<u8> =
593+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
585594

586595
let env: Env = try_into_contract_result!(from_json(env));
587596
let msg: M = try_into_contract_result!(from_json(msg));
@@ -602,9 +611,12 @@ where
602611
C: CustomMsg,
603612
E: ToString,
604613
{
605-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
606-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
607-
let migrate_info = unsafe { Region::from_heap_ptr(migrate_info_ptr).into_vec() };
614+
let env: Vec<u8> =
615+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
616+
let msg: Vec<u8> =
617+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
618+
let migrate_info =
619+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(migrate_info_ptr).unwrap()).into_vec() };
608620

609621
let env: Env = try_into_contract_result!(from_json(env));
610622
let msg: M = try_into_contract_result!(from_json(msg));
@@ -625,8 +637,10 @@ where
625637
C: CustomMsg,
626638
E: ToString,
627639
{
628-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
629-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
640+
let env: Vec<u8> =
641+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
642+
let msg: Vec<u8> =
643+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
630644

631645
let env: Env = try_into_contract_result!(from_json(env));
632646
let msg: M = try_into_contract_result!(from_json(msg));
@@ -645,8 +659,10 @@ where
645659
C: CustomMsg,
646660
E: ToString,
647661
{
648-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
649-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
662+
let env: Vec<u8> =
663+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
664+
let msg: Vec<u8> =
665+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
650666

651667
let env: Env = try_into_contract_result!(from_json(env));
652668
let msg: Reply = try_into_contract_result!(from_json(msg));
@@ -665,8 +681,10 @@ where
665681
M: DeserializeOwned,
666682
E: ToString,
667683
{
668-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
669-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
684+
let env: Vec<u8> =
685+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
686+
let msg: Vec<u8> =
687+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
670688

671689
let env: Env = try_into_contract_result!(from_json(env));
672690
let msg: M = try_into_contract_result!(from_json(msg));
@@ -684,8 +702,10 @@ where
684702
Q: CustomQuery,
685703
E: ToString,
686704
{
687-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
688-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
705+
let env: Vec<u8> =
706+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
707+
let msg: Vec<u8> =
708+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
689709

690710
let env: Env = try_into_contract_result!(from_json(env));
691711
let msg: IbcChannelOpenMsg = try_into_contract_result!(from_json(msg));
@@ -705,8 +725,10 @@ where
705725
C: CustomMsg,
706726
E: ToString,
707727
{
708-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
709-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
728+
let env: Vec<u8> =
729+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
730+
let msg: Vec<u8> =
731+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
710732

711733
let env: Env = try_into_contract_result!(from_json(env));
712734
let msg: IbcChannelConnectMsg = try_into_contract_result!(from_json(msg));
@@ -726,8 +748,10 @@ where
726748
C: CustomMsg,
727749
E: ToString,
728750
{
729-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
730-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
751+
let env: Vec<u8> =
752+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
753+
let msg: Vec<u8> =
754+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
731755

732756
let env: Env = try_into_contract_result!(from_json(env));
733757
let msg: IbcChannelCloseMsg = try_into_contract_result!(from_json(msg));
@@ -747,8 +771,10 @@ where
747771
C: CustomMsg,
748772
E: ToString,
749773
{
750-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
751-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
774+
let env: Vec<u8> =
775+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
776+
let msg: Vec<u8> =
777+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
752778

753779
let env: Env = try_into_contract_result!(from_json(env));
754780
let msg: IbcPacketReceiveMsg = try_into_contract_result!(from_json(msg));
@@ -768,8 +794,10 @@ where
768794
C: CustomMsg,
769795
E: ToString,
770796
{
771-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
772-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
797+
let env: Vec<u8> =
798+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
799+
let msg: Vec<u8> =
800+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
773801

774802
let env: Env = try_into_contract_result!(from_json(env));
775803
let msg: IbcPacketAckMsg = try_into_contract_result!(from_json(msg));
@@ -789,8 +817,10 @@ where
789817
C: CustomMsg,
790818
E: ToString,
791819
{
792-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
793-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
820+
let env: Vec<u8> =
821+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
822+
let msg: Vec<u8> =
823+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
794824

795825
let env: Env = try_into_contract_result!(from_json(env));
796826
let msg: IbcPacketTimeoutMsg = try_into_contract_result!(from_json(msg));
@@ -809,8 +839,10 @@ where
809839
C: CustomMsg,
810840
E: ToString,
811841
{
812-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
813-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
842+
let env: Vec<u8> =
843+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
844+
let msg: Vec<u8> =
845+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
814846

815847
let env: Env = try_into_contract_result!(from_json(env));
816848
let msg: IbcSourceCallbackMsg = try_into_contract_result!(from_json(msg));
@@ -833,8 +865,10 @@ where
833865
C: CustomMsg,
834866
E: ToString,
835867
{
836-
let env: Vec<u8> = unsafe { Region::from_heap_ptr(env_ptr).into_vec() };
837-
let msg: Vec<u8> = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() };
868+
let env: Vec<u8> =
869+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(env_ptr).unwrap()).into_vec() };
870+
let msg: Vec<u8> =
871+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(msg_ptr).unwrap()).into_vec() };
838872

839873
let env: Env = try_into_contract_result!(from_json(env));
840874
let msg: IbcDestinationCallbackMsg = try_into_contract_result!(from_json(msg));

packages/std/src/imports.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloc::vec::Vec;
2+
use core::ptr;
23

34
use crate::import_helpers::{from_high_half, from_low_half};
45
use crate::memory::{Owned, Region};
@@ -133,7 +134,7 @@ impl Storage for ExternalStorage {
133134
}
134135

135136
let value_ptr = read as *mut Region<Owned>;
136-
let data = unsafe { Region::from_heap_ptr(value_ptr) };
137+
let data = unsafe { Region::from_heap_ptr(ptr::NonNull::new(value_ptr).unwrap()) };
137138

138139
Some(data.into_vec())
139140
}
@@ -255,7 +256,7 @@ impl Iterator for ExternalPartialIterator {
255256
}
256257

257258
let data_region = next_result as *mut Region<Owned>;
258-
let data = unsafe { Region::from_heap_ptr(data_region) };
259+
let data = unsafe { Region::from_heap_ptr(ptr::NonNull::new(data_region).unwrap()) };
259260

260261
Some(data.into_vec())
261262
}
@@ -284,7 +285,7 @@ impl Iterator for ExternalIterator {
284285
fn next(&mut self) -> Option<Self::Item> {
285286
let next_result = unsafe { db_next(self.iterator_id) };
286287
let kv_region_ptr = next_result as *mut Region<Owned>;
287-
let kv = unsafe { Region::from_heap_ptr(kv_region_ptr) };
288+
let kv = unsafe { Region::from_heap_ptr(ptr::NonNull::new(kv_region_ptr).unwrap()) };
288289

289290
let (key, value) = decode_sections2(kv.into_vec());
290291

@@ -307,7 +308,7 @@ fn skip_iter(iter_id: u32, count: usize) {
307308
}
308309

309310
// just deallocate the region
310-
unsafe { Region::from_heap_ptr(region as *mut Region<Owned>) };
311+
unsafe { Region::from_heap_ptr(ptr::NonNull::new(region as *mut Region<Owned>).unwrap()) };
311312
}
312313
}
313314

@@ -574,8 +575,12 @@ impl Api for ExternalApi {
574575
let pubkey_ptr = from_low_half(result);
575576
match error_code {
576577
0 => {
577-
let pubkey =
578-
unsafe { Region::from_heap_ptr(pubkey_ptr as *mut Region<Owned>).into_vec() };
578+
let pubkey = unsafe {
579+
Region::from_heap_ptr(
580+
ptr::NonNull::new(pubkey_ptr as *mut Region<Owned>).unwrap(),
581+
)
582+
.into_vec()
583+
};
579584
Ok(pubkey)
580585
}
581586
2 => panic!("MessageTooLong must not happen. This is a bug in the VM."),
@@ -631,8 +636,12 @@ impl Api for ExternalApi {
631636
let pubkey_ptr = from_low_half(result);
632637
match error_code {
633638
0 => {
634-
let pubkey =
635-
unsafe { Region::from_heap_ptr(pubkey_ptr as *mut Region<Owned>).into_vec() };
639+
let pubkey = unsafe {
640+
Region::from_heap_ptr(
641+
ptr::NonNull::new(pubkey_ptr as *mut Region<Owned>).unwrap(),
642+
)
643+
.into_vec()
644+
};
636645
Ok(pubkey)
637646
}
638647
2 => panic!("MessageTooLong must not happen. This is a bug in the VM."),
@@ -712,7 +721,7 @@ impl Api for ExternalApi {
712721
/// Takes a pointer to a Region and reads the data into a String.
713722
/// This is for trusted string sources only.
714723
unsafe fn consume_string_region_written_by_vm(from: *mut Region<Owned>) -> String {
715-
let data = Region::from_heap_ptr(from).into_vec();
724+
let data = Region::from_heap_ptr(ptr::NonNull::new(from).unwrap()).into_vec();
716725
// We trust the VM/chain to return correct UTF-8, so let's save some gas
717726
String::from_utf8_unchecked(data)
718727
}
@@ -732,8 +741,10 @@ impl Querier for ExternalQuerier {
732741
let request_ptr = req.as_ptr() as u32;
733742

734743
let response_ptr = unsafe { query_chain(request_ptr) };
735-
let response =
736-
unsafe { Region::from_heap_ptr(response_ptr as *mut Region<Owned>).into_vec() };
744+
let response = unsafe {
745+
Region::from_heap_ptr(ptr::NonNull::new(response_ptr as *mut Region<Owned>).unwrap())
746+
.into_vec()
747+
};
737748

738749
from_json(&response).unwrap_or_else(|parsing_err| {
739750
SystemResult::Err(SystemError::InvalidResponse {

0 commit comments

Comments
 (0)