Skip to content

Commit

Permalink
Check std::io::Write encoded string is not too long
Browse files Browse the repository at this point in the history
As we did for encoding to a foramtter, before encoding to a
`std::io::Write` writer, check that we do not exceed the spec limit of
90 characters.
  • Loading branch information
tcharding committed Oct 17, 2023
1 parent 1381efe commit fd7d53f
Showing 1 changed file with 53 additions and 3 deletions.
56 changes: 53 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ pub fn encode_to_writer<Ck: Checksum, W: std::io::Write>(
w: &mut W,
hrp: Hrp,
data: &[u8],
) -> Result<(), std::io::Error> {
) -> Result<(), IoEncodeError> {
encode_lower_to_writer::<Ck, W>(w, hrp, data)
}

Expand All @@ -328,7 +328,9 @@ pub fn encode_lower_to_writer<Ck: Checksum, W: std::io::Write>(
w: &mut W,
hrp: Hrp,
data: &[u8],
) -> Result<(), std::io::Error> {
) -> Result<(), IoEncodeError> {
let _ = encoded_length::<Ck>(&hrp, data)?;

let iter = data.iter().copied().bytes_to_fes();
let chars = iter.with_checksum::<Ck>(&hrp).chars();
for c in chars {
Expand All @@ -347,7 +349,9 @@ pub fn encode_upper_to_writer<Ck: Checksum, W: std::io::Write>(
w: &mut W,
hrp: Hrp,
data: &[u8],
) -> Result<(), std::io::Error> {
) -> Result<(), IoEncodeError> {
let _ = encoded_length::<Ck>(&hrp, data)?;

let iter = data.iter().copied().bytes_to_fes();
let chars = iter.with_checksum::<Ck>(&hrp).chars();
for c in chars {
Expand Down Expand Up @@ -506,6 +510,52 @@ impl From<fmt::Error> for EncodeError {
fn from(e: fmt::Error) -> Self { Self::Fmt(e) }
}

/// An error while encoding an address to a `std::io` writer.
#[cfg(feature = "std")]
#[derive(Debug)]
#[non_exhaustive]
pub enum IoEncodeError {
/// Encoding HRP and data into a bech32 string exceeds the spec limit of 90 characters.
TooLong(EncodedLengthError),
/// Error encoding to writer.
Write(std::io::Error),
}

impl fmt::Display for IoEncodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use IoEncodeError::*;

match *self {
TooLong(ref e) => write_err!(f, "encoded string too long"; e),
Write(ref e) => write_err!(f, "error encoding to writer"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for IoEncodeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use IoEncodeError::*;

match *self {
TooLong(ref e) => Some(e),
Write(ref e) => Some(e),
}
}
}

#[cfg(feature = "std")]
impl From<EncodedLengthError> for IoEncodeError {
#[inline]
fn from(e: EncodedLengthError) -> Self { Self::TooLong(e) }
}

#[cfg(feature = "std")]
impl From<std::io::Error> for IoEncodeError {
#[inline]
fn from(e: std::io::Error) -> Self { Self::Write(e) }
}

/// Encoding bech32 string exceeds the spec limit of 90 characters.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
Expand Down

0 comments on commit fd7d53f

Please sign in to comment.