@@ -62,25 +62,51 @@ impl<'a> Multiboot2Header<'a> {
6262 }
6363
6464 /// Find the header in a given slice.
65- pub fn find_header ( buffer : & [ u8 ] ) -> Option < ( & [ u8 ] , u32 ) > {
65+ ///
66+ /// If it succeeds, it returns a tuple consisting of the subslice containing
67+ /// just the header and the index of the header in the given slice.
68+ /// If it fails (either because the header is not properply 64-bit aligned
69+ /// or because it is truncated), it returns a [`BufError`].
70+ /// If there is no header, it returns `None`.
71+ pub fn find_header ( buffer : & [ u8 ] ) -> Result < Option < ( & [ u8 ] , u32 ) > , BufError > {
6672 // the magic is 32 bit aligned and inside the first 8192 bytes
6773 assert ! ( buffer. len( ) >= 8192 ) ;
68- let mut chunks = buffer[ 0 ..8192 ] . chunks_exact ( 4 ) ;
69- let magic_index = match chunks . position ( |vals| {
74+ let mut windows = buffer[ 0 ..8192 ] . windows ( 4 ) ;
75+ let magic_index = match windows . position ( |vals| {
7076 u32:: from_le_bytes ( vals. try_into ( ) . unwrap ( ) ) // yes, there's 4 bytes here
7177 == MULTIBOOT2_HEADER_MAGIC
7278 } ) {
73- Some ( idx) => idx * 4 ,
74- None => return None ,
79+ Some ( idx) => {
80+ if idx % 8 == 0 {
81+ idx
82+ } else {
83+ return Err ( BufError :: Unaligned ) ;
84+ }
85+ }
86+ None => return Ok ( None ) ,
7587 } ;
76- chunks. next ( ) ; // arch
77- let header_length: usize = u32:: from_le_bytes ( chunks. next ( ) . unwrap ( ) . try_into ( ) . unwrap ( ) )
78- . try_into ( )
79- . unwrap ( ) ;
80- Some ( (
88+ // skip over rest of magic
89+ windows. next ( ) ;
90+ windows. next ( ) ;
91+ windows. next ( ) ;
92+ // arch
93+ windows. next ( ) ;
94+ windows. next ( ) ;
95+ windows. next ( ) ;
96+ windows. next ( ) ;
97+ let header_length: usize = u32:: from_le_bytes (
98+ windows
99+ . next ( )
100+ . ok_or ( BufError :: TooSmall ) ?
101+ . try_into ( )
102+ . unwrap ( ) , // 4 bytes are a u32
103+ )
104+ . try_into ( )
105+ . unwrap ( ) ;
106+ Ok ( Some ( (
81107 & buffer[ magic_index..magic_index + header_length] ,
82108 magic_index as u32 ,
83- ) )
109+ ) ) )
84110 }
85111
86112 /// Wrapper around [`Multiboot2BasicHeader::verify_checksum`].
@@ -181,6 +207,16 @@ impl<'a> Debug for Multiboot2Header<'a> {
181207 }
182208}
183209
210+ /// Errors that can occur when parsing a header from a slice.
211+ /// See [`Multiboot2Header::find_header`].
212+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
213+ pub enum BufError {
214+ /// The header in the given slice is truncated.
215+ TooSmall ,
216+ /// The header in the given slice is not properly 64-bit aligned.
217+ Unaligned ,
218+ }
219+
184220/// **Use this only if you know what you do. You probably want to use
185221/// [`Multiboot2Header`] instead.**
186222///
0 commit comments