Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions der/src/asn1/integer/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()? {
Expand Down Expand Up @@ -123,7 +124,7 @@ impl<'a> DecodeValue<'a> for UintRef<'a> {

fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
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() {
Expand Down Expand Up @@ -218,7 +219,8 @@ mod allocating {

fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?;
let result = Self::new(decode_to_slice(bytes.as_slice())?)?;
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() {
Expand Down Expand Up @@ -319,26 +321,26 @@ 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> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is result::Result<&[u8], ErrorKind> ok?
Or should I revert to Result<&[u8]> ?

// The `INTEGER` type always encodes a signed value, so for unsigned
// values the leading `0x00` byte may need to be removed.
//
// We also disallow a leading byte which would overflow a signed ASN.1
// 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),
}
}

/// Decode an unsigned integer into a byte array of the requested size
/// containing a big endian integer.
pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> result::Result<[u8; N], ErrorKind> {
let input = decode_to_slice(bytes)?;

// Compute number of leading zeroes to add
Expand Down Expand Up @@ -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]
Expand Down