Skip to content

Commit 679d422

Browse files
Make it unsafe to define NMI handlers
1 parent 972f60f commit 679d422

9 files changed

+67
-25
lines changed

cortex-m-rt/macros/src/lib.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
113113
.into()
114114
}
115115

116+
#[derive(Debug, PartialEq)]
117+
enum Exception {
118+
DefaultHandler,
119+
HardFault,
120+
NonMaskableInt,
121+
Other,
122+
}
123+
116124
#[proc_macro_attribute]
117125
pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
118126
let mut f = parse_macro_input!(input as ItemFn);
@@ -130,28 +138,38 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
130138
let fspan = f.span();
131139
let ident = f.sig.ident.clone();
132140

133-
enum Exception {
134-
DefaultHandler,
135-
HardFault,
136-
Other,
137-
}
138-
139141
let ident_s = ident.to_string();
140142
let exn = match &*ident_s {
141143
"DefaultHandler" => Exception::DefaultHandler,
142144
"HardFault" => Exception::HardFault,
145+
"NonMaskableInt" => Exception::NonMaskableInt,
143146
// NOTE that at this point we don't check if the exception is available on the target (e.g.
144147
// MemoryManagement is not available on Cortex-M0)
145-
"NonMaskableInt" | "MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault"
146-
| "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => Exception::Other,
148+
"MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault" | "SVCall"
149+
| "DebugMonitor" | "PendSV" | "SysTick" => Exception::Other,
147150
_ => {
148151
return parse::Error::new(ident.span(), "This is not a valid exception name")
149152
.to_compile_error()
150153
.into();
151154
}
152155
};
153156

154-
// XXX should we blacklist other attributes?
157+
if f.sig.unsafety.is_none() {
158+
match exn {
159+
Exception::DefaultHandler | Exception::HardFault | Exception::NonMaskableInt => {
160+
// These are unsafe to define.
161+
let name = if exn == Exception::DefaultHandler {
162+
format!("`DefaultHandler`")
163+
} else {
164+
format!("`{:?}` handler", exn)
165+
};
166+
return parse::Error::new(ident.span(), format_args!("defining a {} is unsafe and requires an `unsafe fn` (see the cortex-m-rt docs)", name))
167+
.to_compile_error()
168+
.into();
169+
}
170+
Exception::Other => {}
171+
}
172+
}
155173

156174
match exn {
157175
Exception::DefaultHandler => {
@@ -174,7 +192,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
174192
if !valid_signature {
175193
return parse::Error::new(
176194
fspan,
177-
"`DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]`",
195+
"`DefaultHandler` must have signature `unsafe fn(i16) [-> !]`",
178196
)
179197
.to_compile_error()
180198
.into();
@@ -231,7 +249,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
231249
if !valid_signature {
232250
return parse::Error::new(
233251
fspan,
234-
"`HardFault` handler must have signature `[unsafe] fn(&ExceptionFrame) -> !`",
252+
"`HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !`",
235253
)
236254
.to_compile_error()
237255
.into();
@@ -257,7 +275,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
257275
)
258276
.into()
259277
}
260-
Exception::Other => {
278+
Exception::NonMaskableInt | Exception::Other => {
261279
let valid_signature = f.sig.constness.is_none()
262280
&& f.vis == Visibility::Inherited
263281
&& f.sig.abi.is_none()

cortex-m-rt/tests/compile-fail/default-handler-bad-signature-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ fn foo() -> ! {
1212
}
1313

1414
#[exception]
15-
fn DefaultHandler(_irqn: i16, undef: u32) {}
16-
//~^ ERROR `DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]`
15+
unsafe fn DefaultHandler(_irqn: i16, undef: u32) {}
16+
//~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]`

cortex-m-rt/tests/compile-fail/default-handler-bad-signature-2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn foo() -> ! {
1212
}
1313

1414
#[exception]
15-
fn DefaultHandler(_irqn: i16) -> u32 {
16-
//~^ ERROR `DefaultHandler` must have signature `[unsafe] fn(i16) [-> !]`
15+
unsafe fn DefaultHandler(_irqn: i16) -> u32 {
16+
//~^ ERROR `DefaultHandler` must have signature `unsafe fn(i16) [-> !]`
1717
0
1818
}

cortex-m-rt/tests/compile-fail/default-handler-hidden.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ mod hidden {
1818
use cortex_m_rt::exception;
1919

2020
#[exception]
21-
fn DefaultHandler(_irqn: i16) {}
21+
unsafe fn DefaultHandler(_irqn: i16) {}
2222
}

cortex-m-rt/tests/compile-fail/default-handler-twice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ fn foo() -> ! {
1212
}
1313

1414
#[exception]
15-
fn DefaultHandler(_irqn: i16) {}
15+
unsafe fn DefaultHandler(_irqn: i16) {}
1616

1717
pub mod reachable {
1818
use cortex_m_rt::exception;
1919

2020
#[exception] //~ ERROR symbol `DefaultHandler` is already defined
21-
fn DefaultHandler(_irqn: i16) {}
21+
unsafe fn DefaultHandler(_irqn: i16) {}
2222
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
extern crate cortex_m_rt;
5+
extern crate panic_halt;
6+
7+
use cortex_m_rt::{entry, exception};
8+
9+
#[entry]
10+
fn foo() -> ! {
11+
loop {}
12+
}
13+
14+
#[exception]
15+
fn DefaultHandler(_irq: i16) {}
16+
//~^ ERROR defining a `DefaultHandler` is unsafe and requires an `unsafe fn`
17+
18+
#[exception]
19+
fn HardFault() {}
20+
//~^ ERROR defining a `HardFault` handler is unsafe and requires an `unsafe fn`
21+
22+
#[exception]
23+
fn NonMaskableInt() {}
24+
//~^ ERROR defining a `NonMaskableInt` handler is unsafe and requires an `unsafe fn`

cortex-m-rt/tests/compile-fail/hard-fault-bad-signature-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn foo() -> ! {
1212
}
1313

1414
#[exception]
15-
fn HardFault(_ef: &ExceptionFrame, undef: u32) -> ! {
16-
//~^ ERROR `HardFault` handler must have signature `[unsafe] fn(&ExceptionFrame) -> !`
15+
unsafe fn HardFault(_ef: &ExceptionFrame, undef: u32) -> ! {
16+
//~^ ERROR `HardFault` handler must have signature `unsafe fn(&ExceptionFrame) -> !`
1717
loop {}
1818
}

cortex-m-rt/tests/compile-fail/hard-fault-twice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ fn foo() -> ! {
1212
}
1313

1414
#[exception]
15-
fn HardFault(_ef: &ExceptionFrame) -> ! {
15+
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
1616
loop {}
1717
}
1818

1919
pub mod reachable {
2020
use cortex_m_rt::{exception, ExceptionFrame};
2121

2222
#[exception] //~ ERROR symbol `HardFault` is already defined
23-
fn HardFault(_ef: &ExceptionFrame) -> ! {
23+
unsafe fn HardFault(_ef: &ExceptionFrame) -> ! {
2424
loop {}
2525
}
2626
}

cortex-m-rt/tests/compile-fail/unsafe-init-static.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ fn SVCall() {
2929
}
3030

3131
#[exception]
32-
fn DefaultHandler(_irq: i16) {
32+
unsafe fn DefaultHandler(_irq: i16) {
3333
static mut X: u32 = init(); //~ ERROR requires unsafe
3434
}
3535

3636
#[exception]
37-
fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! {
37+
unsafe fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! {
3838
static mut X: u32 = init(); //~ ERROR requires unsafe
3939
loop {}
4040
}

0 commit comments

Comments
 (0)