@@ -62,25 +62,51 @@ impl<'a> Multiboot2Header<'a> {
62
62
}
63
63
64
64
/// 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 > {
66
72
// the magic is 32 bit aligned and inside the first 8192 bytes
67
73
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| {
70
76
u32:: from_le_bytes ( vals. try_into ( ) . unwrap ( ) ) // yes, there's 4 bytes here
71
77
== MULTIBOOT2_HEADER_MAGIC
72
78
} ) {
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 ) ,
75
87
} ;
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 ( (
81
107
& buffer[ magic_index..magic_index + header_length] ,
82
108
magic_index as u32 ,
83
- ) )
109
+ ) ) )
84
110
}
85
111
86
112
/// Wrapper around [`Multiboot2BasicHeader::verify_checksum`].
@@ -181,6 +207,16 @@ impl<'a> Debug for Multiboot2Header<'a> {
181
207
}
182
208
}
183
209
210
+ /// Errors that can occur, when parsing a header from a slice.
211
+ /// See [`Multiboot2Header::find_from_slice`].
212
+ #[ derive( Debug ) ]
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
+
184
220
/// **Use this only if you know what you do. You probably want to use
185
221
/// [`Multiboot2Header`] instead.**
186
222
///
0 commit comments