Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Reduce unsafe methods in move-native #249

Open
brson opened this issue Jul 21, 2023 · 2 comments
Open

Reduce unsafe methods in move-native #249

brson opened this issue Jul 21, 2023 · 2 comments
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@brson
Copy link
Collaborator

brson commented Jul 21, 2023

There are a huge number of unsafe functions in move-native, and some safe functions that probably aren't really.

Reducing the number of unsafe methods would help future maintenance and potential auditors.

Most of the unsafety is due to functions interpreting MoveType plus AnyValue or MoveUntypedVector, the fields of which must be trusted to be correct. The basic approach to reducing unsafe functions is to make the fields of these types private, but add unsafe constructors. Then further functions/methods can be safe, assuming the unsafe types were constructed correctly.

Values of these types received from the compiler are assumed correct.

i.e.:

// These fields must maintain safety invariants.
// Because the fields are public, functions operating on MoveType must be unsafe.
// If an unsafe constructor is required to build this, then the constructor caller is responsible for the safety,
// and methods on MoveType can be declared safe.

#[repr(C)]
pub struct MoveType {
    pub name: StaticTypeName,
    pub type_desc: TypeDesc,
    pub type_info: *const TypeInfo,
}

Places where MoveType is combined with an AnyType or MoveUntypedVector can be changed to combine these two types into yet another container, again with an unsafe constructor and private fields, allowing further operations on the pair to be declared safe. Something like this is already done for and TypedMoveBorrowedRustVec and MoveBorrowedRustVecOfStruct, but the methods aren't quite factored correctly to declare methods safe.

e.g.:

// This should be a completely safe method on `TypedMoveBorrowedRustVecMut` -
// the unsafe constructor `borrow_typeed_move_vec_as_rust_vec_mut` should be lifted out
// (and turned into an unsafe constructor method on `TypedMoveBorrowedRustVecMut`).

pub unsafe fn swap(type_ve: &MoveType, v: &mut MoveUntypedVector, i: u64, j: u64) {
    let i = usize::try_from(i).expect("usize");
    let j = usize::try_from(j).expect("usize");

    let rust_vec: TypedMoveBorrowedRustVecMut = borrow_typed_move_vec_as_rust_vec_mut(type_ve, v);

    match rust_vec {
        TypedMoveBorrowedRustVecMut::Bool(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U8(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U16(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U32(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U64(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U128(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::U256(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::Address(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::Signer(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::Vector(_t, mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::Struct(mut v) => v.swap(i, j),
        TypedMoveBorrowedRustVecMut::Reference(_t, mut v) => v.swap(i, j),
    }
}

I'd also like to convert most free functions that operate on these types to methods.

@brson brson added the enhancement New feature or request label Jul 21, 2023
@brson brson self-assigned this Jul 28, 2023
@ksolana
Copy link
Collaborator

ksolana commented Feb 1, 2024

@brson Has this been fixed?

@brson
Copy link
Collaborator Author

brson commented Feb 1, 2024

The low-hanging fruit here is done, but there's so much unsafety in the runtime that there's plenty more that can potentially be done to introduce safe abstractions around the unsafe ones; though there's a question of whether it is worthwhile - the code contortions to make the internal abstractions truly safe will get uglier and may reduce performance.

Off-hand I recall that the vector abstractions still have many functions that are unsafe, and making them actually memory safe looked tricky.

It could be worth someone taking a fresh look at, though I note that creating safe Rust abstractions around unsafe code is pretty tricky and there are a bunch of subtle rules. This page is a good starting point:

https://doc.rust-lang.org/reference/behavior-considered-undefined.html

@brson brson added the help wanted Extra attention is needed label Feb 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants