@@ -150,7 +150,15 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
150150 } )
151151 . collect :: < Vec < _ > > ( ) ;
152152
153+ if let Err ( error) = check_attr_whitelist ( & f. attrs , WhiteListCaller :: Entry ) {
154+ return error;
155+ }
156+
157+ let ( ref cfgs, ref attrs) = extract_cfgs ( f. attrs . clone ( ) ) ;
158+
153159 quote ! (
160+ #( #cfgs) *
161+ #( #attrs) *
154162 #[ doc( hidden) ]
155163 #[ export_name = "main" ]
156164 pub unsafe extern "C" fn #tramp_ident( ) {
@@ -286,6 +294,10 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
286294 . into ( ) ;
287295 }
288296
297+ if let Err ( error) = check_attr_whitelist ( & f. attrs , WhiteListCaller :: Exception ) {
298+ return error;
299+ }
300+
289301 let fspan = f. span ( ) ;
290302 let ident = f. sig . ident . clone ( ) ;
291303
@@ -343,7 +355,11 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
343355 let tramp_ident = Ident :: new ( & format ! ( "{}_trampoline" , f. sig. ident) , Span :: call_site ( ) ) ;
344356 let ident = & f. sig . ident ;
345357
358+ let ( ref cfgs, ref attrs) = extract_cfgs ( f. attrs . clone ( ) ) ;
359+
346360 quote ! (
361+ #( #cfgs) *
362+ #( #attrs) *
347363 #[ doc( hidden) ]
348364 #[ export_name = #ident_s]
349365 pub unsafe extern "C" fn #tramp_ident( ) {
@@ -396,7 +412,11 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
396412 let tramp_ident = Ident :: new ( & format ! ( "{}_trampoline" , f. sig. ident) , Span :: call_site ( ) ) ;
397413 let ident = & f. sig . ident ;
398414
415+ let ( ref cfgs, ref attrs) = extract_cfgs ( f. attrs . clone ( ) ) ;
416+
399417 quote ! (
418+ #( #cfgs) *
419+ #( #attrs) *
400420 #[ doc( hidden) ]
401421 #[ export_name = "HardFault" ]
402422 #[ link_section = ".HardFault.user" ]
@@ -481,7 +501,11 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
481501 } )
482502 . collect :: < Vec < _ > > ( ) ;
483503
504+ let ( ref cfgs, ref attrs) = extract_cfgs ( f. attrs . clone ( ) ) ;
505+
484506 quote ! (
507+ #( #cfgs) *
508+ #( #attrs) *
485509 #[ doc( hidden) ]
486510 #[ export_name = #ident_s]
487511 pub unsafe extern "C" fn #tramp_ident( ) {
@@ -650,7 +674,15 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
650674 } )
651675 . collect :: < Vec < _ > > ( ) ;
652676
677+ if let Err ( error) = check_attr_whitelist ( & f. attrs , WhiteListCaller :: Interrupt ) {
678+ return error;
679+ }
680+
681+ let ( ref cfgs, ref attrs) = extract_cfgs ( f. attrs . clone ( ) ) ;
682+
653683 quote ! (
684+ #( #cfgs) *
685+ #( #attrs) *
654686 #[ doc( hidden) ]
655687 #[ export_name = #ident_s]
656688 pub unsafe extern "C" fn #tramp_ident( ) {
@@ -724,6 +756,10 @@ pub fn pre_init(args: TokenStream, input: TokenStream) -> TokenStream {
724756 . into ( ) ;
725757 }
726758
759+ if let Err ( error) = check_attr_whitelist ( & f. attrs , WhiteListCaller :: PreInit ) {
760+ return error;
761+ }
762+
727763 // XXX should we blacklist other attributes?
728764 let attrs = f. attrs ;
729765 let ident = f. sig . ident ;
@@ -790,6 +826,53 @@ fn extract_cfgs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<Attribute>) {
790826 ( cfgs, not_cfgs)
791827}
792828
829+ enum WhiteListCaller {
830+ Entry ,
831+ Exception ,
832+ Interrupt ,
833+ PreInit ,
834+ }
835+
836+ fn check_attr_whitelist ( attrs : & [ Attribute ] , caller : WhiteListCaller ) -> Result < ( ) , TokenStream > {
837+ let whitelist = & [
838+ "doc" ,
839+ "link_section" ,
840+ "cfg" ,
841+ "allow" ,
842+ "warn" ,
843+ "deny" ,
844+ "forbid" ,
845+ "cold" ,
846+ ] ;
847+
848+ ' o: for attr in attrs {
849+ for val in whitelist {
850+ if eq ( & attr, & val) {
851+ continue ' o;
852+ }
853+ }
854+
855+ let err_str = match caller {
856+ WhiteListCaller :: Entry => "this attribute is not allowed on a cortex-m-rt entry point" ,
857+ WhiteListCaller :: Exception => {
858+ "this attribute is not allowed on an exception handler controlled by cortex-m-rt"
859+ }
860+ WhiteListCaller :: Interrupt => {
861+ "this attribute is not allowed on an interrupt handler controlled by cortex-m-rt"
862+ }
863+ WhiteListCaller :: PreInit => {
864+ "this attribute is not allowed on a pre-init controlled by cortex-m-rt"
865+ }
866+ } ;
867+
868+ return Err ( parse:: Error :: new ( attr. span ( ) , & err_str)
869+ . to_compile_error ( )
870+ . into ( ) ) ;
871+ }
872+
873+ Ok ( ( ) )
874+ }
875+
793876/// Returns `true` if `attr.path` matches `name`
794877fn eq ( attr : & Attribute , name : & str ) -> bool {
795878 attr. style == AttrStyle :: Outer && attr. path . is_ident ( name)
0 commit comments