mirror of
https://github.com/urbit/ares.git
synced 2024-11-22 06:32:47 +03:00
check for backref cycles in cue
This commit is contained in:
parent
d37c4d991f
commit
2124e5b575
@ -5,6 +5,7 @@ use crate::mem::NockStack;
|
|||||||
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D};
|
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D};
|
||||||
use bitvec::prelude::{BitSlice, Lsb0};
|
use bitvec::prelude::{BitSlice, Lsb0};
|
||||||
use either::Either::{Left, Right};
|
use either::Either::{Left, Right};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
crate::gdb!();
|
crate::gdb!();
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ pub fn cue_bitslice(stack: &mut NockStack, buffer: &BitSlice<u64, Lsb0>) -> Resu
|
|||||||
let backref_map = MutHamt::<Noun>::new(stack);
|
let backref_map = MutHamt::<Noun>::new(stack);
|
||||||
let mut result = D(0);
|
let mut result = D(0);
|
||||||
let mut cursor = 0;
|
let mut cursor = 0;
|
||||||
|
let mut in_progress = HashSet::new();
|
||||||
|
|
||||||
let stack_size = stack.size();
|
let stack_size = stack.size();
|
||||||
let input_size = buffer.len();
|
let input_size = buffer.len();
|
||||||
@ -118,12 +120,20 @@ pub fn cue_bitslice(stack: &mut NockStack, buffer: &BitSlice<u64, Lsb0>) -> Resu
|
|||||||
// Capture the destination pointer and pop it off the stack
|
// Capture the destination pointer and pop it off the stack
|
||||||
let dest_ptr: *mut Noun = *(stack.top::<*mut Noun>());
|
let dest_ptr: *mut Noun = *(stack.top::<*mut Noun>());
|
||||||
stack.pop::<*mut Noun>();
|
stack.pop::<*mut Noun>();
|
||||||
|
|
||||||
|
let current_backref = cursor as u64;
|
||||||
|
|
||||||
// 1 bit
|
// 1 bit
|
||||||
if next_bit(&mut cursor, buffer) {
|
if next_bit(&mut cursor, buffer) {
|
||||||
// 11 tag: backref
|
// 11 tag: backref
|
||||||
if next_bit(&mut cursor, buffer) {
|
if next_bit(&mut cursor, buffer) {
|
||||||
|
let backref = rub_backref(&mut cursor, buffer)?;
|
||||||
let mut backref_noun =
|
let mut backref_noun =
|
||||||
Atom::new(stack, rub_backref(&mut cursor, buffer)?).as_noun();
|
Atom::new(stack, backref).as_noun();
|
||||||
|
in_progress.insert(current_backref);
|
||||||
|
if in_progress.contains(&backref) {
|
||||||
|
panic!("Cyclic structure detected during deserialization");
|
||||||
|
}
|
||||||
*dest_ptr = backref_map
|
*dest_ptr = backref_map
|
||||||
.lookup(stack, &mut backref_noun)
|
.lookup(stack, &mut backref_noun)
|
||||||
.ok_or(Deterministic(Exit, D(0)))?;
|
.ok_or(Deterministic(Exit, D(0)))?;
|
||||||
@ -131,18 +141,20 @@ pub fn cue_bitslice(stack: &mut NockStack, buffer: &BitSlice<u64, Lsb0>) -> Resu
|
|||||||
// 10 tag: cell
|
// 10 tag: cell
|
||||||
let (cell, cell_mem_ptr) = Cell::new_raw_mut(stack);
|
let (cell, cell_mem_ptr) = Cell::new_raw_mut(stack);
|
||||||
*dest_ptr = cell.as_noun();
|
*dest_ptr = cell.as_noun();
|
||||||
let mut backref_atom = Atom::new(stack, (cursor - 2) as u64).as_noun();
|
let mut backref_atom = Atom::new(stack, (current_backref - 2) as u64).as_noun();
|
||||||
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
|
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
|
||||||
*(stack.push()) = &mut (*cell_mem_ptr).tail;
|
*(stack.push()) = &mut (*cell_mem_ptr).tail;
|
||||||
*(stack.push()) = &mut (*cell_mem_ptr).head;
|
*(stack.push()) = &mut (*cell_mem_ptr).head;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 0 tag: atom
|
// 0 tag: atom
|
||||||
let backref: u64 = (cursor - 1) as u64;
|
let backref: u64 = (current_backref - 1) as u64;
|
||||||
*dest_ptr = rub_atom(stack, &mut cursor, buffer)?.as_noun();
|
*dest_ptr = rub_atom(stack, &mut cursor, buffer)?.as_noun();
|
||||||
let mut backref_atom = Atom::new(stack, backref).as_noun();
|
let mut backref_atom = Atom::new(stack, backref).as_noun();
|
||||||
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
|
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in_progress.remove(¤t_backref);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user