Skip to content

Commit 90fbb03

Browse files
committed
Safely skip unexpected bytes in the headers
1 parent 2323e5b commit 90fbb03

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

src/header.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use std::io::Read;
1+
use std::io::{Read, Seek, SeekFrom};
22

33
use byteorder::{ByteOrder, ReadBytesExt};
44

55
use super::features::FeatureSet;
66
use super::section::PerfFileSection;
77

8+
const MAGIC_SIZE: usize = 8;
9+
810
/// `perf_header`
911
///
1012
/// The magic number identifies the perf file and the version. Current perf versions
@@ -14,7 +16,7 @@ use super::section::PerfFileSection;
1416
/// endian.
1517
#[derive(Debug, Clone, Copy)]
1618
pub struct PerfHeader {
17-
pub magic: [u8; 8],
19+
pub magic: [u8; MAGIC_SIZE],
1820
/// size of the header
1921
#[allow(dead_code)]
2022
pub header_size: u64,
@@ -28,8 +30,8 @@ pub struct PerfHeader {
2830
}
2931

3032
impl PerfHeader {
31-
pub fn parse<R: Read>(mut reader: R) -> Result<Self, std::io::Error> {
32-
let mut magic = [0; 8];
33+
pub fn parse<R: Read + Seek>(mut reader: R) -> Result<Self, std::io::Error> {
34+
let mut magic = [0; MAGIC_SIZE];
3335
reader.read_exact(&mut magic)?;
3436

3537
if magic[0] == b'P' {
@@ -39,9 +41,9 @@ impl PerfHeader {
3941
}
4042
}
4143

42-
fn parse_impl<R: Read, T: ByteOrder>(
44+
fn parse_impl<R: Read + Seek, T: ByteOrder>(
4345
mut reader: R,
44-
magic: [u8; 8],
46+
magic: [u8; MAGIC_SIZE],
4547
) -> Result<Self, std::io::Error> {
4648
let header_size = reader.read_u64::<T>()?;
4749
let attr_size = reader.read_u64::<T>()?;
@@ -54,6 +56,14 @@ impl PerfHeader {
5456
reader.read_u64::<T>()?,
5557
reader.read_u64::<T>()?,
5658
]);
59+
60+
// Skip any additional header bytes from newer formats. Size excludes magic.
61+
let known_size = (std::mem::size_of::<Self>() - MAGIC_SIZE) as u64;
62+
if header_size > known_size {
63+
let extra_bytes = header_size - known_size;
64+
reader.seek(SeekFrom::Current(extra_bytes as i64))?;
65+
}
66+
5767
Ok(Self {
5868
magic,
5969
header_size,
@@ -74,22 +84,31 @@ impl PerfHeader {
7484
/// file sections.
7585
#[derive(Debug, Clone, Copy)]
7686
pub struct PerfPipeHeader {
77-
pub magic: [u8; 8],
87+
pub magic: [u8; MAGIC_SIZE],
7888
/// size of the header (should be 16)
7989
#[allow(dead_code)]
8090
pub size: u64,
8191
}
8292

8393
impl PerfPipeHeader {
8494
pub fn parse<R: Read>(mut reader: R) -> Result<Self, std::io::Error> {
85-
let mut magic = [0; 8];
95+
let mut magic = [0; MAGIC_SIZE];
8696
reader.read_exact(&mut magic)?;
8797

8898
let size = if magic[0] == b'P' {
8999
reader.read_u64::<byteorder::LittleEndian>()?
90100
} else {
91101
reader.read_u64::<byteorder::BigEndian>()?
92102
};
103+
104+
// Skip any additional header bytes from newer formats. size excludes magic.
105+
// Use io::copy to sink instead of seek since pipe mode doesn't support seeking.
106+
let known_size = (std::mem::size_of::<Self>() - MAGIC_SIZE) as u64;
107+
if size > known_size {
108+
let extra_bytes = size - known_size;
109+
std::io::copy(&mut reader.by_ref().take(extra_bytes), &mut std::io::sink())?;
110+
}
111+
93112
Ok(Self { magic, size })
94113
}
95114
}

0 commit comments

Comments
 (0)