Skip to content

Commit 9e8bdbd

Browse files
committed
limit resync iteration if there is no progress
1 parent 22a05f2 commit 9e8bdbd

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

crates/libafl_intelpt/src/decoder.rs

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ 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,
6+
enc_dec_builder::EncoderDecoderBuilder,
7+
error::{PtError, PtErrorCode},
8+
event::EventType,
9+
image::Image,
10+
status::Status,
711
};
812
use num_traits::SaturatingAdd;
913

@@ -81,21 +85,46 @@ where
8185
}
8286

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

90119
match self.resync_loop() {
91120
Ok(()) if self.status.eos() => return Ok(()),
92121
Ok(()) => (),
93-
Err(e) => return Err(e),
122+
Err(e) => return Err(error_from_pt_error(e)),
94123
}
95124
}
96125
}
97126

98-
fn resync_loop(&mut self) -> Result<(), Error>
127+
fn resync_loop(&mut self) -> Result<(), PtError>
99128
where
100129
T: SaturatingAdd + From<u8> + Debug,
101130
{
@@ -108,41 +137,22 @@ where
108137
Err(e) => match e.code() {
109138
PtErrorCode::Eos => return Ok(()),
110139
PtErrorCode::EventIgnored => self.handle_event()?,
111-
_ => return Err(Error::illegal_state(format!("PT error in resync {e:?}"))),
140+
_ => return Err(e),
112141
},
113142
}
114143
}
115144
}
116145

117-
fn decode_blocks_loop(&mut self) -> Result<(), Error>
146+
fn decode_blocks_loop(&mut self) -> Result<(), PtError>
118147
where
119148
T: SaturatingAdd + From<u8> + Debug,
120149
{
121-
#[cfg(debug_assertions)]
122-
let mut trace_entry_iters: (u64, u64) = (0, 0);
123-
124150
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-
141151
while self.status.event_pending() {
142152
self.handle_event()?;
143153
}
144154

145-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
155+
let offset = self.decoder.offset()?;
146156
if self.should_ignore_vmx_root() || offset <= self.trace_skip {
147157
self.ignore_block()?;
148158
} else {
@@ -155,7 +165,7 @@ where
155165
}
156166
}
157167

158-
fn decode_block(&mut self) -> Result<(), Error> {
168+
fn decode_block(&mut self) -> Result<(), PtError> {
159169
match self.decoder.decode_next() {
160170
Ok((b, s)) => {
161171
self.status = s;
@@ -172,37 +182,37 @@ where
172182
}
173183
Err(e) => {
174184
if e.code() != PtErrorCode::Eos {
175-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
185+
let offset = self.decoder.offset()?;
176186
log::info!(
177187
"PT error in block next {e:?} trace offset {offset:x} last decoded block end {:x}",
178188
self.previous_block_end_ip
179189
);
180190
}
181-
Err(error_from_pt_error(e))
191+
Err(e)
182192
}
183193
}
184194
}
185195

186-
fn ignore_block(&mut self) -> Result<(), Error> {
196+
fn ignore_block(&mut self) -> Result<(), PtError> {
187197
match self.decoder.decode_next() {
188198
Ok((_, s)) => {
189199
self.status = s;
190200
Ok(())
191201
}
192202
Err(e) => {
193203
if e.code() != PtErrorCode::Eos {
194-
let offset = self.decoder.offset().map_err(error_from_pt_error)?;
204+
let offset = self.decoder.offset()?;
195205
log::trace!(
196206
"PT error in ignore block {e:?} trace offset {offset:x} last decoded block end {:x}",
197207
self.previous_block_end_ip
198208
);
199209
}
200-
Err(error_from_pt_error(e))
210+
Err(e)
201211
}
202212
}
203213
}
204214

205-
fn handle_event(&mut self) -> Result<(), Error> {
215+
fn handle_event(&mut self) -> Result<(), PtError> {
206216
match self.decoder.event() {
207217
Ok((event, s)) => {
208218
self.status = s;
@@ -213,7 +223,7 @@ where
213223
}
214224
Ok(())
215225
}
216-
Err(e) => Err(Error::illegal_state(format!("PT error in event {e:?}"))),
226+
Err(e) => Err(e),
217227
}
218228
}
219229

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)