aboutsummaryrefslogtreecommitdiff
path: root/macros/src
diff options
context:
space:
mode:
authorGravatar Emil Fresk <emil.fresk@gmail.com> 2021-02-21 16:15:34 +0100
committerGravatar Emil Fresk <emil.fresk@gmail.com> 2021-02-21 16:15:34 +0100
commit1a46345a2aa710c4ec5ea8fb6589424bc4450d0f (patch)
tree9204b0dec5b5efa3baa0d0468fc6c30a8964a1eb /macros/src
parent555f36857ec93bed26ff4249593992f500b7c4ab (diff)
downloadrtic-1a46345a2aa710c4ec5ea8fb6589424bc4450d0f.tar.gz
rtic-1a46345a2aa710c4ec5ea8fb6589424bc4450d0f.tar.zst
rtic-1a46345a2aa710c4ec5ea8fb6589424bc4450d0f.zip
Fixed UB in generated `Monotonic::now()`
Diffstat (limited to 'macros/src')
-rw-r--r--macros/src/codegen.rs19
-rw-r--r--macros/src/codegen/post_init.rs2
-rw-r--r--macros/src/codegen/timer_queue.rs17
3 files changed, 26 insertions, 12 deletions
diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs
index f75a8f2d..b1e87ca8 100644
--- a/macros/src/codegen.rs
+++ b/macros/src/codegen.rs
@@ -112,9 +112,12 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
.iter()
.map(|(_, monotonic)| {
let name = &monotonic.ident;
+ let name_str = &name.to_string();
let ty = &monotonic.ty;
- let mangled_name = util::mangle_monotonic_type(&name.to_string());
- let ident = util::monotonic_ident(&name.to_string());
+ let mangled_name = util::mangle_monotonic_type(&name_str);
+ let ident = util::monotonic_ident(&name_str);
+ let panic_str = &format!("Use of monotonic '{}' before it was passed to the runtime", name_str);
+
quote! {
pub use rtic::Monotonic as _;
@@ -123,14 +126,20 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
#[allow(non_snake_case)]
pub mod #name {
+ /// Access the global `Monotonic` implementation, not that this will panic
+ /// before the this `Monotonic` has been passed to the RTIC runtime.
pub fn now() -> rtic::time::Instant<#app_path::#mangled_name> {
rtic::export::interrupt::free(|_| {
use rtic::Monotonic as _;
use rtic::time::Clock as _;
- if let Ok(v) = unsafe{ (&*#app_path::#ident.as_ptr()).try_now() } {
- v
+ if let Some(m) = unsafe{ #app_path::#ident.as_ref() } {
+ if let Ok(v) = m.try_now() {
+ v
+ } else {
+ unreachable!("Your monotonic is not infallible!")
+ }
} else {
- unreachable!("Your monotonic is not infallible!")
+ panic!(#panic_str);
}
})
}
diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs
index b6cf47c3..8ebcb12b 100644
--- a/macros/src/codegen/post_init.rs
+++ b/macros/src/codegen/post_init.rs
@@ -35,7 +35,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
// Store the monotonic
let name = util::monotonic_ident(&monotonic.to_string());
- stmts.push(quote!(#name.as_mut_ptr().write(monotonics.#idx);));
+ stmts.push(quote!(#name = Some(monotonics.#idx);));
}
// Enable the interrupts -- this completes the `init`-ialization phase
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
index 54b2c1f0..65560680 100644
--- a/macros/src/codegen/timer_queue.rs
+++ b/macros/src/codegen/timer_queue.rs
@@ -69,11 +69,11 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
let mono = util::monotonic_ident(&monotonic_name);
let doc = &format!("Storage for {}", monotonic_name);
- let mono_ty = quote!(core::mem::MaybeUninit<#m>);
+ let mono_ty = quote!(Option<#m>);
items.push(quote!(
#[doc = #doc]
- static mut #mono: #mono_ty = core::mem::MaybeUninit::uninit();
+ static mut #mono: #mono_ty = None;
));
}
@@ -122,10 +122,15 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
#[no_mangle]
#[allow(non_snake_case)]
unsafe fn #bound_interrupt() {
- while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue(
- || #disable_isr,
- &mut *#app_path::#m_ident.as_mut_ptr(),
- ))
+
+ while let Some((task, index)) = rtic::export::interrupt::free(|_|
+ if let Some(mono) = #app_path::#m_ident.as_mut() {
+ #tq.dequeue(|| #disable_isr, mono)
+ } else {
+ // We can only use the timer queue if `init` has returned, and it
+ // writes the `Some(monotonic)` we are accessing here.
+ core::hint::unreachable_unchecked()
+ })
{
match task {
#(#arms)*