Add encode::Error::MissingData variant

The `io::Error` is troublesome because it contains a bunch of stuff that
never happens when reading from a buffer. However the EOF variant can
occur if the buffer is too short. As an initial step towards reducing
usage of the `io::Error` add a `MissingData` variant to the
`encode::Error` and when converting from an IO error map to
`MissingData` if EOF is encountered.
This commit is contained in:
Tobin C. Harding 2024-10-18 10:11:54 +11:00
parent 5a42ef2850
commit b04142c745
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
3 changed files with 18 additions and 8 deletions

View File

@ -1027,13 +1027,11 @@ mod tests {
])
.is_err());
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
// Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive,
// by making sure it fails with IO Error and not an `OversizedVectorAllocation` Error.
// by making sure it fails with `MissingData` and not an `OversizedVectorAllocation` Error.
let err =
deserialize::<CheckedData>(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err();
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
assert!(matches!(err, Error::MissingData));
test_len_is_max_vec::<u8>();
test_len_is_max_vec::<BlockHash>();
@ -1055,11 +1053,10 @@ mod tests {
Vec<T>: Decodable,
T: fmt::Debug,
{
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
let mut buf = Vec::new();
buf.emit_compact_size(super::MAX_VEC_SIZE / mem::size_of::<T>()).unwrap();
let err = deserialize::<Vec<T>>(&buf).unwrap_err();
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
assert!(matches!(err, Error::MissingData));
}
#[test]

View File

@ -56,6 +56,8 @@ impl<E: fmt::Debug + std::error::Error + 'static> std::error::Error for DecodeEr
pub enum Error {
/// And I/O error.
Io(io::Error),
/// Missing data (early end of file or slice too short).
MissingData, // TODO: Can we add more context?
/// Tried to allocate an oversized vector.
OversizedVectorAllocation {
/// The capacity requested.
@ -86,6 +88,7 @@ impl fmt::Display for Error {
match *self {
Io(ref e) => write_err!(f, "IO error"; e),
MissingData => write!(f, "missing data (early end of file or slice too short)"),
OversizedVectorAllocation { requested: ref r, max: ref m } =>
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m),
InvalidChecksum { expected: ref e, actual: ref a } =>
@ -105,7 +108,8 @@ impl std::error::Error for Error {
match self {
Io(e) => Some(e),
OversizedVectorAllocation { .. }
MissingData
| OversizedVectorAllocation { .. }
| InvalidChecksum { .. }
| NonMinimalVarInt
| ParseFailed(_)
@ -115,7 +119,14 @@ impl std::error::Error for Error {
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self { Error::Io(error) }
fn from(e: io::Error) -> Self {
use io::ErrorKind;
match e.kind() {
ErrorKind::UnexpectedEof => Error::MissingData,
_ => Error::Io(e),
}
}
}
/// Hex deserialization error.

View File

@ -361,6 +361,8 @@ impl<D: fmt::Display> serde::de::Expected for DisplayExpected<D> {
fn consensus_error_into_serde<E: serde::de::Error>(error: ConsensusError) -> E {
match error {
ConsensusError::Io(error) => panic!("unexpected IO error {:?}", error),
ConsensusError::MissingData =>
E::custom("missing data (early end of file or slice too short)"),
ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!(
"the requested allocation of {} items exceeds maximum of {}",
requested, max