Skip to content

Commit c41081c

Browse files
committed
Check std::io::Write encoded string is not too long
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.
1 parent 1822c15 commit c41081c

File tree

1 file changed

+53
-3
lines changed

1 file changed

+53
-3
lines changed

src/lib.rs

+53-3
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ pub fn encode_to_writer<Ck: Checksum, W: std::io::Write>(
314314
w: &mut W,
315315
hrp: Hrp,
316316
data: &[u8],
317-
) -> Result<(), std::io::Error> {
317+
) -> Result<(), IoEncodeError> {
318318
encode_lower_to_writer::<Ck, W>(w, hrp, data)
319319
}
320320

@@ -328,7 +328,9 @@ pub fn encode_lower_to_writer<Ck: Checksum, W: std::io::Write>(
328328
w: &mut W,
329329
hrp: Hrp,
330330
data: &[u8],
331-
) -> Result<(), std::io::Error> {
331+
) -> Result<(), IoEncodeError> {
332+
let _ = encoded_length::<Ck>(&hrp, data)?;
333+
332334
let iter = data.iter().copied().bytes_to_fes();
333335
let chars = iter.with_checksum::<Ck>(&hrp).chars();
334336
for c in chars {
@@ -347,7 +349,9 @@ pub fn encode_upper_to_writer<Ck: Checksum, W: std::io::Write>(
347349
w: &mut W,
348350
hrp: Hrp,
349351
data: &[u8],
350-
) -> Result<(), std::io::Error> {
352+
) -> Result<(), IoEncodeError> {
353+
let _ = encoded_length::<Ck>(&hrp, data)?;
354+
351355
let iter = data.iter().copied().bytes_to_fes();
352356
let chars = iter.with_checksum::<Ck>(&hrp).chars();
353357
for c in chars {
@@ -506,6 +510,52 @@ impl From<fmt::Error> for EncodeError {
506510
fn from(e: fmt::Error) -> Self { Self::Fmt(e) }
507511
}
508512

513+
/// An error while encoding an address to a `std::io` writer.
514+
#[cfg(feature = "std")]
515+
#[derive(Debug)]
516+
#[non_exhaustive]
517+
pub enum IoEncodeError {
518+
/// Encoding HRP and data into a bech32 string exceeds the spec limit of 90 characters.
519+
TooLong(EncodedLengthError),
520+
/// Error encoding to writer.
521+
Write(std::io::Error),
522+
}
523+
524+
impl fmt::Display for IoEncodeError {
525+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
526+
use IoEncodeError::*;
527+
528+
match *self {
529+
TooLong(ref e) => write_err!(f, "encoded string too long"; e),
530+
Write(ref e) => write_err!(f, "error encoding to writer"; e),
531+
}
532+
}
533+
}
534+
535+
#[cfg(feature = "std")]
536+
impl std::error::Error for IoEncodeError {
537+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
538+
use IoEncodeError::*;
539+
540+
match *self {
541+
TooLong(ref e) => Some(e),
542+
Write(ref e) => Some(e),
543+
}
544+
}
545+
}
546+
547+
#[cfg(feature = "std")]
548+
impl From<EncodedLengthError> for IoEncodeError {
549+
#[inline]
550+
fn from(e: EncodedLengthError) -> Self { Self::TooLong(e) }
551+
}
552+
553+
#[cfg(feature = "std")]
554+
impl From<std::io::Error> for IoEncodeError {
555+
#[inline]
556+
fn from(e: std::io::Error) -> Self { Self::Write(e) }
557+
}
558+
509559
/// Encoding bech32 string exceeds the spec limit of 90 characters.
510560
#[derive(Debug, Clone, PartialEq, Eq)]
511561
#[non_exhaustive]

0 commit comments

Comments
 (0)