Skip to content

Commit e739390

Browse files
committed
limit resync iteration if there is no progress
1 parent 1d59a6f commit e739390

File tree

2 files changed

+44
-36
lines changed

2 files changed

+44
-36
lines changed

crates/libafl_intelpt/src/decoder.rs

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use core::fmt::Debug;
22

33
use libafl_bolts::{Error, hash_64_fast};
44
use libipt::{
5-
block::BlockDecoder, enc_dec_builder::EncoderDecoderBuilder, error::PtErrorCode,
6-
event::EventType, image::Image, status::Status,
5+
block::BlockDecoder, enc_dec_builder::EncoderDecoderBuilder, error::PtError,
6+
error::PtErrorCode, event::EventType, image::Image, status::Status,
77
};
88
use num_traits::SaturatingAdd;
99

@@ -81,21 +81,46 @@ where
8181
}
8282

8383
fn decode_and_resync_loop(&mut self) -> Result<(), Error> {
84+
const MAX_RESYNC_TRIALS: usize = 32;
85+
let mut last_error_offset = 0;
86+
let mut last_error_count = 0;
87+
8488
loop {
8589
match self.decode_blocks_loop() {
86-
Ok(()) if self.status.eos() => return Ok(()),
87-
Ok(()) | Err(_) => (),
90+
Ok(()) => {
91+
debug_assert!(
92+
self.status.eos(),
93+
"PT decoder decode_blocks_loop should return Ok only at the end of stream"
94+
);
95+
return Ok(());
96+
}
97+
Err(e) if e.code() == PtErrorCode::Eos => return Ok(()),
98+
Err(_) => (),
99+
}
100+
101+
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
102+
if offset == last_error_offset {
103+
last_error_count += 1;
104+
if last_error_count > MAX_RESYNC_TRIALS {
105+
return Err(Error::illegal_state(format!(
106+
"PT Decoder got stuck at trace offset {offset:x}.\
107+
Make sure the decoder Image has the right content and offsets.\
108+
Trying to continue decoding.",
109+
)));
110+
}
111+
} else {
112+
last_error_offset = offset;
88113
}
89114

90115
match self.resync_loop() {
91116
Ok(()) if self.status.eos() => return Ok(()),
92117
Ok(()) => (),
93-
Err(e) => return Err(e),
118+
Err(e) => return Err(error_from_pt_error(e)),
94119
}
95120
}
96121
}
97122

98-
fn resync_loop(&mut self) -> Result<(), Error>
123+
fn resync_loop(&mut self) -> Result<(), PtError>
99124
where
100125
T: SaturatingAdd + From<u8> + Debug,
101126
{
@@ -108,41 +133,22 @@ where
108133
Err(e) => match e.code() {
109134
PtErrorCode::Eos => return Ok(()),
110135
PtErrorCode::EventIgnored => self.handle_event()?,
111-
_ => return Err(Error::illegal_state(format!("PT error in resync {e:?}"))),
136+
_ => return Err(e),
112137
},
113138
}
114139
}
115140
}
116141

117-
fn decode_blocks_loop(&mut self) -> Result<(), Error>
142+
fn decode_blocks_loop(&mut self) -> Result<(), PtError>
118143
where
119144
T: SaturatingAdd + From<u8> + Debug,
120145
{
121-
#[cfg(debug_assertions)]
122-
let mut trace_entry_iters: (u64, u64) = (0, 0);
123-
124146
loop {
125-
#[cfg(debug_assertions)]
126-
{
127-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
128-
if trace_entry_iters.0 == offset {
129-
trace_entry_iters.1 += 1;
130-
if trace_entry_iters.1 > 1000 {
131-
return Err(Error::illegal_state(format!(
132-
"PT Decoder got stuck at trace offset {offset:x}.\
133-
Make sure the decoder Image has the right content and offsets.",
134-
)));
135-
}
136-
} else {
137-
trace_entry_iters = (offset, 0);
138-
}
139-
}
140-
141147
while self.status.event_pending() {
142148
self.handle_event()?;
143149
}
144150

145-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
151+
let offset = self.decoder.offset()?;
146152
if self.should_ignore_vmx_root() || offset <= self.trace_skip {
147153
self.ignore_block()?;
148154
} else {
@@ -155,7 +161,7 @@ where
155161
}
156162
}
157163

158-
fn decode_block(&mut self) -> Result<(), Error> {
164+
fn decode_block(&mut self) -> Result<(), PtError> {
159165
match self.decoder.decode_next() {
160166
Ok((b, s)) => {
161167
self.status = s;
@@ -172,37 +178,37 @@ where
172178
}
173179
Err(e) => {
174180
if e.code() != PtErrorCode::Eos {
175-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
181+
let offset = self.decoder.offset()?;
176182
log::info!(
177183
"PT error in block next {e:?} trace offset {offset:x} last decoded block end {:x}",
178184
self.previous_block_end_ip
179185
);
180186
}
181-
Err(error_from_pt_error(e))
187+
Err(e)
182188
}
183189
}
184190
}
185191

186-
fn ignore_block(&mut self) -> Result<(), Error> {
192+
fn ignore_block(&mut self) -> Result<(), PtError> {
187193
match self.decoder.decode_next() {
188194
Ok((_, s)) => {
189195
self.status = s;
190196
Ok(())
191197
}
192198
Err(e) => {
193199
if e.code() != PtErrorCode::Eos {
194-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
200+
let offset = self.decoder.offset()?;
195201
log::trace!(
196202
"PT error in ignore block {e:?} trace offset {offset:x} last decoded block end {:x}",
197203
self.previous_block_end_ip
198204
);
199205
}
200-
Err(error_from_pt_error(e))
206+
Err(e)
201207
}
202208
}
203209
}
204210

205-
fn handle_event(&mut self) -> Result<(), Error> {
211+
fn handle_event(&mut self) -> Result<(), PtError> {
206212
match self.decoder.event() {
207213
Ok((event, s)) => {
208214
self.status = s;
@@ -213,7 +219,7 @@ where
213219
}
214220
Ok(())
215221
}
216-
Err(e) => Err(Error::illegal_state(format!("PT error in event {e:?}"))),
222+
Err(e) => Err(e),
217223
}
218224
}
219225

crates/libafl_intelpt/src/linux.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ impl IntelPT {
243243
(ptr, None)
244244
} else {
245245
// Head pointer wrapped, the trace is split
246+
log::trace!("Handling split trace");
246247
let mut owned_data = self.join_split_trace(head_wrap, tail_wrap);
248+
debug_assert_eq!(owned_data.len(), len);
247249
(owned_data.as_mut_ptr(), Some(owned_data))
248250
}
249251
};

0 commit comments

Comments
 (0)