Skip to content

Commit f8ad17b

Browse files
Fix_temp_segment_chain_bug
1 parent e2c6c91 commit f8ad17b

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

vm/src/vm/vm_memory/memory.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,95 @@ impl Memory {
286286
}
287287
Ok(addr.into())
288288
}
289+
#[cfg(not(feature = "extensive_hints"))]
290+
fn flatten_relocation_rules(&mut self) -> Result<(), MemoryError> {
291+
let keys: Vec<usize> = self.relocation_rules.keys().copied().collect();
292+
let max_hops = self.relocation_rules.len().saturating_add(1);
293+
for key in keys {
294+
let mut dst = *self
295+
.relocation_rules
296+
.get(&key)
297+
.expect("key taken from keys vec must exist");
298+
299+
let mut hops = 0usize;
300+
while dst.segment_index < 0 {
301+
let next_key = (-(dst.segment_index + 1)) as usize;
302+
let next = *self.relocation_rules.get(&next_key).ok_or_else(|| {
303+
MemoryError::UnallocatedSegment(Box::new((next_key, self.temp_data.len())))
304+
})?;
305+
dst = (next + dst.offset).map_err(MemoryError::Math)?;
306+
hops += 1;
307+
if hops > max_hops {
308+
return Err(MemoryError::Relocation); // cycle guard
309+
}
310+
}
311+
self.relocation_rules.insert(key, dst);
312+
}
313+
Ok(())
314+
}
315+
316+
#[cfg(feature = "extensive_hints")]
317+
fn flatten_relocation_rules(&mut self) -> Result<(), MemoryError> {
318+
let keys: Vec<usize> = self.relocation_rules.keys().copied().collect();
319+
let max_hops = self.relocation_rules.len().saturating_add(1);
320+
for key in keys {
321+
let mut dst = self
322+
.relocation_rules
323+
.get(&key)
324+
.expect("key taken from keys vec must exist")
325+
.clone();
326+
327+
let mut hops = 0usize;
328+
loop {
329+
match dst {
330+
MaybeRelocatable::RelocatableValue(r) if r.segment_index < 0 => {
331+
let next_key = (-(r.segment_index + 1)) as usize;
332+
let next = self
333+
.relocation_rules
334+
.get(&next_key)
335+
.ok_or_else(|| {
336+
MemoryError::UnallocatedSegment(Box::new((
337+
next_key,
338+
self.temp_data.len(),
339+
)))
340+
})?
341+
.clone();
342+
343+
match next {
344+
MaybeRelocatable::RelocatableValue(nr) => {
345+
dst = MaybeRelocatable::RelocatableValue(
346+
(nr + r.offset).map_err(MemoryError::Math)?,
347+
);
348+
}
349+
MaybeRelocatable::Int(i) => {
350+
if r.offset != 0 {
351+
return Err(MemoryError::NonZeroOffset(r.offset));
352+
}
353+
MaybeRelocatable::Int(i)
354+
}
355+
}
356+
}
357+
_ => break,
358+
}
359+
hops += 1;
360+
if hops > max_hops {
361+
return Err(MemoryError::Relocation);
362+
}
363+
}
364+
self.relocation_rules.insert(key, dst);
365+
}
366+
Ok(())
367+
}
289368

290369
/// Relocates the memory according to the relocation rules and clears `self.relocaction_rules`.
291370
pub fn relocate_memory(&mut self) -> Result<(), MemoryError> {
292371
if self.relocation_rules.is_empty() || self.temp_data.is_empty() {
293372
return Ok(());
294373
}
374+
375+
// flatten chains (temp->temp->...->real).
376+
self.flatten_relocation_rules()?;
377+
295378
// Relocate temporary addresses in memory
296379
for segment in self.data.iter_mut().chain(self.temp_data.iter_mut()) {
297380
for cell in segment.iter_mut() {
@@ -345,6 +428,7 @@ impl Memory {
345428
self.relocation_rules.clear();
346429
Ok(())
347430
}
431+
348432
/// Add a new relocation rule.
349433
///
350434
/// When using feature "extensive_hints" the destination is allowed to be an Integer (via

0 commit comments

Comments
 (0)