mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
add check memory border while reading/writing memory; improve parsing wat
This commit is contained in:
parent
05c2d9ddda
commit
c92344272b
@ -158,22 +158,34 @@ impl Parse<'_> for RecordType {
|
||||
fn parse(parser: Parser<'_>) -> Result<Self> {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
parser.parse::<keyword::string>()?;
|
||||
let record_name = parser.parse()?;
|
||||
let record_name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
let mut fields = vec![];
|
||||
|
||||
while !parser.is_empty() {
|
||||
fields.push(parser.parens(|parser| {
|
||||
parser.parse::<keyword::string>()?;
|
||||
let name = parser.parse()?;
|
||||
|
||||
parser.parens(|parser| {
|
||||
while !parser.is_empty() {
|
||||
parser.parse::<keyword::field>()?;
|
||||
|
||||
let name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
let ty = parser.parse()?;
|
||||
|
||||
Ok(RecordFieldType { name, ty })
|
||||
})?);
|
||||
}
|
||||
fields.push(RecordFieldType { name, ty });
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(RecordType {
|
||||
name: record_name,
|
||||
|
@ -77,7 +77,7 @@ impl ToString for &InterfaceType {
|
||||
InterfaceType::Anyref => "anyref".to_string(),
|
||||
InterfaceType::I32 => "i32".to_string(),
|
||||
InterfaceType::I64 => "i64".to_string(),
|
||||
InterfaceType::Record(record_type) => record_type.to_string(),
|
||||
InterfaceType::Record(record_type_id) => format!("record {}", record_type_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ impl ToString for &InterfaceType {
|
||||
impl ToString for &RecordType {
|
||||
fn to_string(&self) -> String {
|
||||
format!(
|
||||
"record {} {{\n{fields}}}",
|
||||
"record ${} {{\n{fields}}}",
|
||||
self.name,
|
||||
fields = self
|
||||
.fields
|
||||
@ -93,7 +93,7 @@ impl ToString for &RecordType {
|
||||
.fold(String::new(), |mut accumulator, field_type| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&format!(
|
||||
"{}: {}\n",
|
||||
"field ${}: {}\n",
|
||||
field_type.name,
|
||||
(&field_type.ty).to_string()
|
||||
));
|
||||
|
@ -284,6 +284,12 @@ where
|
||||
)
|
||||
})?;
|
||||
|
||||
log::trace!(
|
||||
"record.lift_memory: record {:?} resolved for type id {}",
|
||||
record_type,
|
||||
record_type_id
|
||||
);
|
||||
|
||||
let record = record_lift_memory_(&**instance, record_type, offset, instruction)?;
|
||||
|
||||
log::trace!("record.lift_memory: pushing {:?} on the stack", record);
|
||||
@ -327,7 +333,7 @@ where
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction, value.as_bytes())?
|
||||
} else {
|
||||
0i32
|
||||
0
|
||||
};
|
||||
|
||||
result.push(string_pointer as _);
|
||||
@ -338,7 +344,7 @@ where
|
||||
let byte_array_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction, &value)?
|
||||
} else {
|
||||
0i32
|
||||
0
|
||||
};
|
||||
|
||||
result.push(byte_array_pointer as _);
|
||||
@ -348,7 +354,6 @@ where
|
||||
InterfaceValue::Record(values) => {
|
||||
let record_ptr = record_lower_memory_(instance, instruction, values)?;
|
||||
|
||||
log::trace!("record.lower_memory: pushing {:?} on the stack", record_ptr);
|
||||
result.push(record_ptr as _);
|
||||
}
|
||||
}
|
||||
@ -357,7 +362,7 @@ where
|
||||
let result = safe_transmute::transmute_to_bytes::<u64>(&result);
|
||||
let result_pointer = write_to_instance_mem(instance, instruction, &result)?;
|
||||
|
||||
Ok(result_pointer)
|
||||
Ok(result_pointer as _)
|
||||
}
|
||||
|
||||
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
@ -386,7 +391,12 @@ where
|
||||
&record_fields,
|
||||
instruction,
|
||||
)?;
|
||||
|
||||
log::trace!("record.lower_memory: obtained {:?} values on the stack for record type = {}", record_fields, record_type_id);
|
||||
|
||||
let offset = record_lower_memory_(*instance, instruction, record_fields)?;
|
||||
|
||||
log::trace!("record.lower_memory: pushing {:?} on the stack", offset);
|
||||
runtime.stack.push(InterfaceValue::I32(offset));
|
||||
|
||||
Ok(())
|
||||
|
@ -35,6 +35,19 @@ where
|
||||
})?
|
||||
.view();
|
||||
|
||||
log::info!("reading {} bytes from offset {}", size, offset);
|
||||
|
||||
let right = offset + size;
|
||||
if right < offset || right >= memory_view.len() {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: right,
|
||||
length: memory_view.len(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Ok((&memory_view[offset..offset + size])
|
||||
.iter()
|
||||
.map(std::cell::Cell::get)
|
||||
@ -45,7 +58,7 @@ pub(super) fn write_to_instance_mem<'instance, Instance, Export, LocalImport, Me
|
||||
instance: &'instance Instance,
|
||||
instruction: Instruction,
|
||||
bytes: &[u8],
|
||||
) -> Result<i32, InstructionError>
|
||||
) -> Result<usize, InstructionError>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
@ -53,7 +66,7 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let mem_pointer = allocate(instance, instruction, bytes.len() as _)?;
|
||||
let offset = allocate(instance, instruction, bytes.len() as _)?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_view = instance
|
||||
@ -66,18 +79,31 @@ where
|
||||
})?
|
||||
.view();
|
||||
|
||||
for (byte_id, byte) in bytes.iter().enumerate() {
|
||||
memory_view[mem_pointer as usize + byte_id].set(*byte);
|
||||
log::info!("writing {} bytes from offset {}", bytes.len(), offset);
|
||||
|
||||
let right = offset + bytes.len();
|
||||
if right < offset || right >= memory_view.len() {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: right,
|
||||
length: memory_view.len(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Ok(mem_pointer)
|
||||
for (byte_id, byte) in bytes.iter().enumerate() {
|
||||
memory_view[offset + byte_id].set(*byte);
|
||||
}
|
||||
|
||||
Ok(offset)
|
||||
}
|
||||
|
||||
pub(super) fn allocate<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
instruction: Instruction,
|
||||
size: i32,
|
||||
) -> Result<i32, InstructionError>
|
||||
size: usize,
|
||||
) -> Result<usize, InstructionError>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
@ -89,7 +115,7 @@ where
|
||||
instance,
|
||||
ALLOCATE_FUNC_INDEX,
|
||||
instruction,
|
||||
vec![InterfaceValue::I32(size)],
|
||||
vec![InterfaceValue::I32(size as _)],
|
||||
)?;
|
||||
if values.len() != 1 {
|
||||
return Err(InstructionError::new(
|
||||
@ -101,7 +127,7 @@ where
|
||||
},
|
||||
));
|
||||
}
|
||||
to_native::<i32>(&values[0], instruction)
|
||||
to_native::<i32>(&values[0], instruction).map(|v| v as usize)
|
||||
}
|
||||
|
||||
pub(super) fn deallocate<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
|
Loading…
Reference in New Issue
Block a user