From 33f0eba0495e197e699678a6ac9f1e5a43b7e11c Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:47:43 +0100 Subject: [PATCH 1/3] der: track reader error position in `Uint::decode_value` --- der/src/asn1/integer/uint.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index 9c0024078..1dc67c7f9 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -5,7 +5,7 @@ use crate::{ AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, ord::OrdIsValueOrd, }; -use core::cmp::Ordering; +use core::{cmp::Ordering, result}; #[cfg(feature = "alloc")] pub use allocating::Uint; @@ -33,7 +33,8 @@ macro_rules! impl_encoding_traits { } let bytes = reader.read_into(&mut buf[..max_length])?; - let result = Self::from_be_bytes(decode_to_array(bytes)?); + let bytes = decode_to_array(bytes).map_err(|kind| reader.error(kind))?; + let result = Self::from_be_bytes(bytes); // Ensure we compute the same encoded length as the original any value if header.length() != result.value_len()? { @@ -123,7 +124,7 @@ impl<'a> DecodeValue<'a> for UintRef<'a> { fn decode_value>(reader: &mut R, header: Header) -> Result { let bytes = <&'a BytesRef>::decode_value(reader, header)?.as_slice(); - let result = Self::new(decode_to_slice(bytes)?)?; + let result = Self::new(decode_to_slice(bytes).map_err(|kind| reader.error(kind))?)?; // Ensure we compute the same encoded length as the original any value. if result.value_len()? != header.length() { @@ -218,7 +219,8 @@ mod allocating { fn decode_value>(reader: &mut R, header: Header) -> Result { let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?; - let result = Self::new(decode_to_slice(bytes.as_slice())?)?; + let result = + Self::new(decode_to_slice(bytes.as_slice()).map_err(|kind| reader.error(kind))?)?; // Ensure we compute the same encoded length as the original any value. if result.value_len()? != header.length() { @@ -319,7 +321,7 @@ mod allocating { /// zeroes removed. /// /// Returns a byte array of the requested size containing a big endian integer. -pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> { +pub(crate) fn decode_to_slice(bytes: &[u8]) -> result::Result<&[u8], ErrorKind> { // The `INTEGER` type always encodes a signed value, so for unsigned // values the leading `0x00` byte may need to be removed. // @@ -338,7 +340,7 @@ pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> { /// Decode an unsigned integer into a byte array of the requested size /// containing a big endian integer. -pub(super) fn decode_to_array(bytes: &[u8]) -> Result<[u8; N]> { +pub(super) fn decode_to_array(bytes: &[u8]) -> result::Result<[u8; N], ErrorKind> { let input = decode_to_slice(bytes)?; // Compute number of leading zeroes to add @@ -412,20 +414,20 @@ mod tests { #[test] fn decode_to_array_extra_zero() { let err = decode_to_array::<4>(&[0, 1, 2]).err().unwrap(); - assert_eq!(err.kind(), ErrorKind::Noncanonical { tag: Tag::Integer }); + assert_eq!(err, ErrorKind::Noncanonical { tag: Tag::Integer }); } #[test] fn decode_to_array_missing_zero() { // We're decoding an unsigned integer, but this value would be signed let err = decode_to_array::<4>(&[0xFF, 0xFE]).err().unwrap(); - assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer }); + assert_eq!(err, ErrorKind::Value { tag: Tag::Integer }); } #[test] fn decode_to_array_oversized_input() { let err = decode_to_array::<1>(&[1, 2, 3]).err().unwrap(); - assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer }); + assert_eq!(err, ErrorKind::Length { tag: Tag::Integer }); } #[test] From 51b639425377f258a999c65368263c4d6a55a2a8 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:49:34 +0100 Subject: [PATCH 2/3] der: let bytes = decode_to_slice --- der/src/asn1/integer/uint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index 1dc67c7f9..28857ccc3 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -219,8 +219,8 @@ mod allocating { fn decode_value>(reader: &mut R, header: Header) -> Result { let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?; - let result = - Self::new(decode_to_slice(bytes.as_slice()).map_err(|kind| reader.error(kind))?)?; + let bytes = decode_to_slice(bytes.as_slice()).map_err(|kind| reader.error(kind))?; + let result = Self::new(bytes)?; // Ensure we compute the same encoded length as the original any value. if result.value_len()? != header.length() { From 924968b96fb976c90bc0d763a273933e34b51633 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:56:47 +0100 Subject: [PATCH 3/3] der: cargo clippy fixes --- der/src/asn1/integer/uint.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index 28857ccc3..d8838430c 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -329,11 +329,11 @@ pub(crate) fn decode_to_slice(bytes: &[u8]) -> result::Result<&[u8], ErrorKind> // integer (since we're decoding an unsigned integer). // We expect all such cases to have a leading `0x00` byte. match bytes { - [] => Err(Tag::Integer.non_canonical_error().into()), + [] => Err(Tag::Integer.non_canonical_error()), [0] => Ok(bytes), - [0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error().into()), + [0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()), [0, rest @ ..] => Ok(rest), - [byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error().into()), + [byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error()), _ => Ok(bytes), } }