Open ia0 opened 4 months ago
Here's a list of a search for Result<.*, Trap>
I'll go through them checking if we should return errors instead
./crates/scheduler/src/call/timer.rs
105:) -> Result<Id<board::Timer<B>>, Trap> {
This should return Result<_, Error>
with Error::user(Code::OutOfBounds)
for invalid timer IDs. This should just propagate the error from Id::new
. We could also add a Code::ResourceExhausted
error for scheduler.timers[timer].is_none()
.
./crates/scheduler/src/call/crypto/ccm.rs
88:fn ensure_support<B: Board>() -> Result<(), Trap> {
./crates/scheduler/src/call/crypto/gcm.rs
102:fn ensure_support<B: Board>() -> Result<(), Trap> {
This should also just return Result<_, Error>
with Error::user(Code::OutOfBounds)
./crates/scheduler/src/lib.rs
419: fn disable_event(&mut self, key: Key<B>) -> Result<(), Trap> {
./crates/scheduler/src/call/usb/serial.rs
103:fn convert_event(event: u32) -> Result<Event, Trap> {
./crates/scheduler/src/call/radio/ble.rs
82:fn convert_event(event: u32) -> Result<Event, Trap> {
./crates/scheduler/src/call/uart.rs
140:fn convert_event<B: Board>(uart: Id<board::Uart<B>>, event: u32) -> Result<Event<B>, Trap> {
These should return Result<_, Error>
with Error::user(Code::InvalidArgument)
. This would only happen if the user
supplied a bad event from the api
./crates/scheduler/src/applet.rs
166: pub fn enable(&mut self, handler: Handler<B>) -> Result<(), Trap> {
176: pub fn disable(&mut self, key: Key<B>) -> Result<(), Trap> {
These should return Error::user(Code::InvalidState). User shouldn't be inserting more than one event handler for a given key.
./crates/scheduler/src/applet.rs
106: pub fn insert(&mut self, hash: HashContext<B>) -> Result<usize, Trap> {
112: pub fn get_mut(&mut self, id: usize) -> Result<&mut HashContext<B>, Trap> {
116: pub fn take(&mut self, id: usize) -> Result<HashContext<B>, Trap> {
Looking at references to AppletHashes::{insert, get_mut, take}
it looks like user supplies these ids, so i'd say Error::user(Code::OutOfBounds)
would be a suitable error code to return instead of trapping.
./crates/scheduler/src/applet/store.rs
36: fn get(&self, ptr: u32, len: u32) -> Result<&[u8], Trap>;
37: fn get_mut(&self, ptr: u32, len: u32) -> Result<&mut [u8], Trap>;
37: fn alloc(&mut self, size: u32, align: u32) -> Result<u32, Error>;
These should remain trapping, though the user supplies what appears to be the key, the result is dependent on the board implementation.
40: fn get_opt(&self, ptr: u32, len: u32) -> Result<Option<&[u8]>, Trap> {
47: fn get_array<const LEN: usize>(&self, ptr: u32) -> Result<&[u8; LEN], Trap> {
51: fn get_array_mut<const LEN: usize>(&self, ptr: u32) -> Result<&mut [u8; LEN], Trap> {
56: fn from_bytes<T: AnyBitPattern>(&self, ptr: u32) -> Result<&T, Trap> {
61: fn from_bytes_mut<T: NoUninit + AnyBitPattern>(&self, ptr: u32) -> Result<&mut T, Trap> {
65: fn alloc_copy(&mut self, ptr_ptr: u32, len_ptr: Option<u32>, data: &[u8]) -> Result<(), Trap> {
Think these should also remain trapping being transitively from the above.
./crates/scheduler/src/call/crypto/hash.rs
247:fn convert_hash_algorithm<B: Board>(algorithm: u32) -> Result<Result<Algorithm, Trap>, Trap> {
262:fn convert_hmac_algorithm<B: Board>(algorithm: u32) -> Result<Result<Algorithm, Trap>, Trap> {
These should return Result<_, Error>
with Error::user(Code::InvalidArgument)
. This would only happen if the user
supplied a bad algorithm from the api
./crates/scheduler/src/applet/store/wasm.rs
88: fn borrow(&self, range: Range<usize>) -> Result<(), Trap> {
92: fn borrow_mut(&self, range: Range<usize>) -> Result<(), Trap> {
97: fn borrow_impl(&self, y: (bool, Range<usize>)) -> Result<(), Trap> {
These I'm not sure.
./crates/scheduler/src/call/crypto/ec.rs
220:fn convert_curve<B: Board>(curve: u32) -> Result<Result<Curve, Trap>, Trap> {
These should return Result<_, Error>
with Error::user(Code::InvalidArgument)
. This would only happen if the user
supplied a curve from the api
Thanks for putting up this list (though you could have made a PR directly)! I'll go through them using the <file>:<line>
you provided. Note that searching for Result<_, Trap>
is not enough. For example in call/timer.rs
, there are many map_err(|_| Trap)
that could be errors instead.
crates/scheduler/src/call/timer.rs:105
: I agree we should return an error. Once we have multiple applets, we shouldn't use a 1-to-1 mapping between the board ids and the applet ids, and instead have a level of indirection like file descriptors in linux. This would mean that the error should probably be InvalidArgument
.
crates/scheduler/src/call/crypto/ccm.rs:88
and gcm.rs:102
: I agree this should return an error, namely User:NotImplemented
. Note that contrary to or_fail
, the blame is on the user not the world, since there's a function to check support.
crates/scheduler/src/lib.rs:419
: I'm splitting this because anything outside src/call
is not necessarily an applet error. I agree that disabling a non-existing key should be an error, namely User:NotFound
. I'm not sure how to deal with such top-level functions that return Result<_, Error>
where the error is already at the applet level. Maybe the best is to return Result<_, Failure>
to indicate that it a user-level error.
crates/scheduler/src/call/usb/serial.rs:103
and friends: Yes, we should return an error, namely User:InvalidArgument
.
crates/scheduler/src/applet.rs:166
: That's similar to the Applet::disable
above. We should return Failure
with User:InvalidState
or User:InvalidArgument
. Ideally we should add an AlreadyExist
error code.
crates/scheduler/src/applet.rs:106
and friends: For insert
the error should be World:NotEnough
. For get_mut
and take
, it should be User:OutOfBounds
for the first Trap
and User:NotFound
(or InvalidArgument
) for the second.
crates/scheduler/src/applet/store.rs:36
and friends: Yes, let's keep bad memory accesses as traps.
crates/scheduler/src/call/crypto/hash.rs:247
and friends: The first trap (i.e. outer one) should be User:InvalidArgument
. The second User:NotImplemented
(i.e. inner one).
crates/scheduler/src/applet/store/wasm.rs:88
and friends: This should stay a trap. This is also bad memory management from the applet (for example trying to break mutability xor aliasing).
crates/scheduler/src/call/crypto/ec.rs:220
: Yes, this is similar to the call/crypto/hash.rs:247
case. Outer trap should be User:InvalidArgument
. Inner trap should be User:NotImplemented
.
Search for all functions returning
Result<_, Trap>
and fix them if needed.Good candidates are:
MemoryApi::alloc()
should returnWorld:NotEnough
(or something similar).Applet::{enable,disable}()
should probably returnUser::InvalidState
.Scheduler::disable_event()
is similar to above.or_trap!()
should be replaced withor_fail!()
.Bad candidates are:
MemoryApi::{get,get_mut}()
) should continue toTrap
.The distinction is not always clear. It would be good to come up with a criteria of whether an operation should trap or error.
This is part of #43.