diff options
author | 2021-02-21 16:15:34 +0100 | |
---|---|---|
committer | 2021-02-21 16:15:34 +0100 | |
commit | 1a46345a2aa710c4ec5ea8fb6589424bc4450d0f (patch) | |
tree | 9204b0dec5b5efa3baa0d0468fc6c30a8964a1eb /macros/src | |
parent | 555f36857ec93bed26ff4249593992f500b7c4ab (diff) | |
download | rtic-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.rs | 19 | ||||
-rw-r--r-- | macros/src/codegen/post_init.rs | 2 | ||||
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 17 |
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)* |