-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move SensorId
validation to clients, and reply fault when invalid
#1683
Conversation
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
cd6b2b5
to
8e502eb
Compare
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
SensorId
validation to clients, and reply fault when invalid
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
8e502eb
to
0eaefb5
Compare
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
ugh, clippy's mad about some more stuff, gimme a sec... |
|
||
// | ||
// We pack per-`NoData` counters into a u32. | ||
// | ||
let (nbits, shift) = nodata.counter_encoding::<u32>(); | ||
let mask = (1 << nbits) - 1; | ||
let mask = (1u32 << nbits).saturating_sub(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to remove overflow checks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was hoping we could completely get rid of panics --- unfortunately, we can't, as the generated idol
server code has some potential panic paths, but eliminating overflow checks here does shave a few bytes off the flash size regardless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more nits, but generally looks good – it's great to see more APIs become infallible!
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. The `host-sp-messages` crate is changed to replace the use of `SensorId` with `u32`, as it deals with _un-validated_ sensor indices received from the host over IPCC. `host-sp-comms` will validate these sensor IDs before calling into sensor IPC methods. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
870c320
to
a3878d1
Compare
Now that `host-sp-messages` no longer depends on `task-sensor-types`, there's really no reason for it to be a separate crate. Thus, let's just move the error types into `task-sensor-api`.
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. The `host-sp-messages` crate is changed to replace the use of `SensorId` with `u32`, as it deals with _un-validated_ sensor indices received from the host over IPCC. `host-sp-comms` will validate these sensor IDs before calling into sensor IPC methods. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
Now that `host-sp-messages` no longer depends on `task-sensor-types`, there's really no reason for it to be a separate crate. Thus, let's just move the error types into `task-sensor-api`.
a3878d1
to
de3c75e
Compare
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. The `host-sp-messages` crate is changed to replace the use of `SensorId` with `u32`, as it deals with _un-validated_ sensor indices received from the host over IPCC. `host-sp-comms` will validate these sensor IDs before calling into sensor IPC methods. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
Now that `host-sp-messages` no longer depends on `task-sensor-types`, there's really no reason for it to be a separate crate. Thus, let's just move the error types into `task-sensor-api`.
de3c75e
to
87e314c
Compare
The `SensorId` type represents an index into an array of sensors in the `sensors` server task. Currently, this is validated by the sensors server, returning `SensorError::InvalidSensor` if it is out of range. However, the sensor IDs used by firmware code are hard-coded by code generation and should never be out of range, so in most cases, an invalid `SensorId` should not occur and should be considered a bug. Only `host-spc-comms` will ever request sensor IDs that are out of range, if the upstack code requests an ID that doesn't exist on this device. Therefore, we ought to change the sensor API to use reply-fault on receipt of an invalid `SensorId`, rather than returning an error. This commit prepares for such a change by adding client-side validation of `SensorId`s with a `TryFrom` impl, and a panicking `SensorId::new` This way, the tasks that *can* handle sensor IDs from the outside world (`host-sp-comms`) can validate that sensor IDs received from the outside world are valid _before_ calling into the sensor task API, and reject any invalid IDs. In a subsequent PR, `task_sensor_api` will be updated to remove the `InvalidSensor` error type. The `host-sp-messages` crate is changed to replace the use of `SensorId` with `u32`, as it deals with _un-validated_ sensor indices received from the host over IPCC. `host-sp-comms` will validate these sensor IDs before calling into sensor IPC methods. A nice side benefit of using the panicking `const fn new` in generated code is that...it's const fn, and the code generation mostly uses it in `const` initializers. So, if any of the code generation accidentally emits an invalid sensor ID, we'll actually get a build-time rather than runtime error, which seems nice!
Currently, a number of IPCs in the `Sensor` API return a `SensorApiError` type, which represents either "invalid sensor ID" or "no reading". Since passing an invalid `SensorId` to the sensors API will now result in a reply-fault, there's no reason to return an error type that can represent that case. This commit changes the `Sensor` API to return `Option<T>`s rather than `Result<T, SensorApiError>`, with `None` representing the "no reading" case. Fixes #1680
Now that we can guarantee all `SensorId`s are valid indices, we can also eliminate all bounds-checked array indexing, and return `RequestError::Fail(ClientError::BadMessageContents)` instead. This shaves off 240B of flash, which is...less than I had hoped.
This shaves off a few more bytes of flash, although we'd also need to get rid of panics in idol-generated code to completely eliminate panic formatting from the sensor task...
As described in #1680, the
sensors
API currently validatesSensorID
s in the server task and returns an error when they are invalid. We can simplify the IPC interface by doing this validation on the client side, and reply-faulting any clients who send an invalid ID, instead. This branch does that.This PR consists of a sequence of commits which are intended to be reviewed individually.