Skip to content

Commit ed46a10

Browse files
committed
segwit: Check encoded string is not too long
Currently it is possible to encode a string that is more than 90 characters long, this is in violation of BIP-173. We recently added a function `crate::segwit::encoded_length` that does the length check, call it when encoding in functions that already do other validity checks and explicitly comment its absence in the `*_unchecked` functions. Also document the validity checks in `encode_v0` and `encode_v1`.
1 parent d09c7b1 commit ed46a10

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

src/segwit.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ pub fn decode(s: &str) -> Result<(Hrp, Fe32, Vec<u8>), DecodeError> {
8080

8181
/// Encodes a segwit address.
8282
///
83-
/// Does validity checks on the `witness_version` and length checks on the `witness_program`.
83+
/// Does validity checks on the `witness_version`, length checks on the `witness_program`, and
84+
/// checks the total encoded string length.
8485
///
8586
/// As specified by [`BIP-350`] we use the [`Bech32m`] checksum algorithm for witness versions 1 and
8687
/// above, and for witness version 0 we use the original ([`BIP-173`]) [`Bech32`] checksum
@@ -101,20 +102,27 @@ pub fn encode(
101102
) -> Result<String, EncodeError> {
102103
segwit::validate_witness_version(witness_version)?;
103104
segwit::validate_witness_program_length(witness_program.len(), witness_version)?;
105+
let _ = encoded_length(hrp, witness_version, witness_program)?;
104106

105107
let mut buf = String::new();
106108
encode_to_fmt_unchecked(&mut buf, hrp, witness_version, witness_program)?;
107109
Ok(buf)
108110
}
109111

110112
/// Encodes a segwit version 0 address.
113+
///
114+
/// Does validity checks on the `witness_version`, length checks on the `witness_program`, and
115+
/// checks the total encoded string length.
111116
#[cfg(feature = "alloc")]
112117
#[inline]
113118
pub fn encode_v0(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
114119
encode(hrp, VERSION_0, witness_program)
115120
}
116121

117122
/// Encodes a segwit version 1 address.
123+
///
124+
/// Does validity checks on the `witness_version`, length checks on the `witness_program`, and
125+
/// checks the total encoded string length.
118126
#[cfg(feature = "alloc")]
119127
#[inline]
120128
pub fn encode_v1(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeError> {
@@ -123,8 +131,9 @@ pub fn encode_v1(hrp: &Hrp, witness_program: &[u8]) -> Result<String, EncodeErro
123131

124132
/// Encodes a segwit address to a writer ([`fmt::Write`]) using lowercase characters.
125133
///
126-
/// Does not check the validity of the witness version and witness program lengths (see
127-
/// the [`crate::primitives::segwit`] module for validation functions).
134+
/// Does not check the validity of the witness version, the witness program length, or the total
135+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
136+
/// validation functions).
128137
#[inline]
129138
pub fn encode_to_fmt_unchecked<W: fmt::Write>(
130139
fmt: &mut W,
@@ -137,8 +146,9 @@ pub fn encode_to_fmt_unchecked<W: fmt::Write>(
137146

138147
/// Encodes a segwit address to a writer ([`fmt::Write`]) using lowercase characters.
139148
///
140-
/// Does not check the validity of the witness version and witness program lengths (see
141-
/// the [`crate::primitives::segwit`] module for validation functions).
149+
/// Does not check the validity of the witness version, the witness program length, or the total
150+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
151+
/// validation functions).
142152
pub fn encode_lower_to_fmt_unchecked<W: fmt::Write>(
143153
fmt: &mut W,
144154
hrp: &Hrp,
@@ -165,8 +175,9 @@ pub fn encode_lower_to_fmt_unchecked<W: fmt::Write>(
165175
///
166176
/// This is provided for use when creating QR codes.
167177
///
168-
/// Does not check the validity of the witness version and witness program lengths (see
169-
/// the [`crate::primitives::segwit`] module for validation functions).
178+
/// Does not check the validity of the witness version, the witness program length, or the total
179+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
180+
/// validation functions).
170181
#[inline]
171182
pub fn encode_upper_to_fmt_unchecked<W: fmt::Write>(
172183
fmt: &mut W,
@@ -193,8 +204,9 @@ pub fn encode_upper_to_fmt_unchecked<W: fmt::Write>(
193204

194205
/// Encodes a segwit address to a writer ([`std::io::Write`]) using lowercase characters.
195206
///
196-
/// Does not check the validity of the witness version and witness program lengths (see
197-
/// the [`crate::primitives::segwit`] module for validation functions).
207+
/// Does not check the validity of the witness version, the witness program length, or the total
208+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
209+
/// validation functions).
198210
#[cfg(feature = "std")]
199211
#[inline]
200212
pub fn encode_to_writer_unchecked<W: std::io::Write>(
@@ -208,8 +220,9 @@ pub fn encode_to_writer_unchecked<W: std::io::Write>(
208220

209221
/// Encodes a segwit address to a writer ([`std::io::Write`]) using lowercase characters.
210222
///
211-
/// Does not check the validity of the witness version and witness program lengths (see
212-
/// the [`crate::primitives::segwit`] module for validation functions).
223+
/// Does not check the validity of the witness version, the witness program length, or the total
224+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
225+
/// validation functions).
213226
#[cfg(feature = "std")]
214227
#[inline]
215228
pub fn encode_lower_to_writer_unchecked<W: std::io::Write>(
@@ -238,8 +251,9 @@ pub fn encode_lower_to_writer_unchecked<W: std::io::Write>(
238251
///
239252
/// This is provided for use when creating QR codes.
240253
///
241-
/// Does not check the validity of the witness version and witness program lengths (see
242-
/// the [`crate::primitives::segwit`] module for validation functions).
254+
/// Does not check the validity of the witness version, the witness program length, or the total
255+
/// encoded string length (see [`encoded_length`] and the [`crate::primitives::segwit`] module for
256+
/// validation functions).
243257
#[cfg(feature = "std")]
244258
#[inline]
245259
pub fn encode_upper_to_writer_unchecked<W: std::io::Write>(
@@ -364,6 +378,8 @@ pub enum EncodeError {
364378
WitnessVersion(InvalidWitnessVersionError),
365379
/// Invalid witness length.
366380
WitnessLength(WitnessLengthError),
381+
/// Encoding HRP, witver, and program into a bech32 string exceeds limit of 90 characters.
382+
TooLong(EncodedLengthError),
367383
/// Writing to formatter failed.
368384
Write(fmt::Error),
369385
}
@@ -375,6 +391,7 @@ impl fmt::Display for EncodeError {
375391
match *self {
376392
WitnessVersion(ref e) => write_err!(f, "witness version"; e),
377393
WitnessLength(ref e) => write_err!(f, "witness length"; e),
394+
TooLong(ref e) => write_err!(f, "encoded string too long"; e),
378395
Write(ref e) => write_err!(f, "writing to formatter failed"; e),
379396
}
380397
}
@@ -388,6 +405,7 @@ impl std::error::Error for EncodeError {
388405
match *self {
389406
WitnessVersion(ref e) => Some(e),
390407
WitnessLength(ref e) => Some(e),
408+
TooLong(ref e) => Some(e),
391409
Write(ref e) => Some(e),
392410
}
393411
}
@@ -403,6 +421,11 @@ impl From<WitnessLengthError> for EncodeError {
403421
fn from(e: WitnessLengthError) -> Self { Self::WitnessLength(e) }
404422
}
405423

424+
impl From<EncodedLengthError> for EncodeError {
425+
#[inline]
426+
fn from(e: EncodedLengthError) -> Self { Self::TooLong(e) }
427+
}
428+
406429
impl From<fmt::Error> for EncodeError {
407430
#[inline]
408431
fn from(e: fmt::Error) -> Self { Self::Write(e) }

0 commit comments

Comments
 (0)