mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 06:10:58 +00:00
Check total
This commit is contained in:
@@ -281,6 +281,12 @@ const EXPONENT_BYTES: usize = 4;
|
||||
/// to a scratch buffer, so the input stays borrowed rather than copied. The two output
|
||||
/// regions are judged after the input, and the mantissa's region before the exponent's,
|
||||
/// so the first fault reported is the leftmost.
|
||||
///
|
||||
/// The two widths are the ABI's rather than the guest's, so the length the host reports
|
||||
/// is checked against their sum for equality rather than as a bound, and ahead of the
|
||||
/// output regions: a wrong total means there is no answer to place, whatever the guest
|
||||
/// declared. That is a fatal error and not a status, since the guest asked for nothing
|
||||
/// wrong.
|
||||
pub(crate) fn write_mant_exp(
|
||||
caller: &mut Caller<'_, VmState<'_>>,
|
||||
mantissa_out: Region,
|
||||
@@ -299,6 +305,14 @@ pub(crate) fn write_mant_exp(
|
||||
|
||||
let total = call(host, data, mant_buf, exp_buf)?;
|
||||
|
||||
// Both buffers are fixed-width and were offered whole, so the only length the host
|
||||
// can correctly report is their sum. Anything else is the host contradicting the
|
||||
// ABI: with the widths in doubt, part of what would be copied out is whatever the
|
||||
// previous call left in the buffer, so none of it is copied.
|
||||
if total != MANTISSA_BYTES + EXPONENT_BYTES {
|
||||
return Err(HostError::InternalFatal.into());
|
||||
}
|
||||
|
||||
// Copy the mantissa, then the exponent, each only if its whole value fits its
|
||||
// region — a region too small is `BufferTooSmall`, with nothing written.
|
||||
let mant_range = mantissa_out.range()?;
|
||||
@@ -324,7 +338,7 @@ pub(crate) fn write_mant_exp(
|
||||
#[expect(
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_possible_wrap,
|
||||
reason = "the total is 12, far inside i32"
|
||||
reason = "a total other than 12 returned above, and 12 is far inside i32"
|
||||
)]
|
||||
let total = total as i32;
|
||||
Ok(total)
|
||||
|
||||
@@ -935,6 +935,24 @@ fn float_to_mant_exp_writes_both_regions() {
|
||||
assert_eq!(status(&wat, &host), 9, "the exponent's first byte");
|
||||
}
|
||||
|
||||
/// The widths that call writes are the ABI's, so a host reporting any other total has
|
||||
/// contradicted it: the regions are wide enough and the guest asked for nothing wrong,
|
||||
/// yet the mantissa is short of its eight bytes, so the rest of what would be copied is
|
||||
/// whatever the buffer already held. The run stops instead.
|
||||
#[test]
|
||||
fn float_to_mant_exp_with_a_wrong_total_stops_the_run() {
|
||||
let host = FakeHost::new().answering_float_mant_exp(vec![1, 2, 3, 4], vec![9, 10, 11, 12]);
|
||||
|
||||
let wat = module(
|
||||
&[import::FLOAT_TO_MANT_EXP, ONE_PAGE],
|
||||
"(call $float_to_mant_exp (i32.const 0) (i32.const 8) (i32.const 64) (i32.const 8) (i32.const 80) (i32.const 4))",
|
||||
);
|
||||
assert!(
|
||||
matches!(failure(&wat, &host).error, RunError::Internal),
|
||||
"a total that is not the two widths must stop the run"
|
||||
);
|
||||
}
|
||||
|
||||
/// A comparison that reads two float regions and returns a scalar verdict, no output
|
||||
/// region involved.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user