blob: 6ffc0832b6353e588a5c5473ac476067de87b35c [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use cbor::*;
use rust_gtest_interop::prelude::*;
fn parse_bytes<'a>(input: &'a [u8]) -> Result<Value<'a>, Error> {
let len = input.len();
let result = parse_with_config(input, Config::default())?;
if result.bytes_consumed < len {
Err(Error::ExtraneousData)
} else {
Ok(result.value)
}
}
#[gtest(CBORReaderRustTest, TestInputs)]
fn test_inputs() {
let test_cases = [
("", Err(Error::IncompleteCborData)),
("d0", Err(Error::UnsupportedMajorType)),
("1f", Err(Error::UnknownAdditionalInfo)),
("01", Ok(Value::Int(1))),
("0100", Err(Error::ExtraneousData)),
("20", Ok(Value::Int(-1))),
("182a", Ok(Value::Int(42))),
("191388", Ok(Value::Int(5000))),
("1a02faf080", Ok(Value::Int(50000000))),
("1b000000746a528800", Ok(Value::Int(500000000000))),
("1bffffffffffffffff", Err(Error::OutOfRangeIntegerValue)),
("3bffffffffffffffff", Err(Error::OutOfRangeIntegerValue)),
("1818", Ok(Value::Int(24))),
("1817", Err(Error::NonMinimalCborEncoding)),
("190080", Err(Error::NonMinimalCborEncoding)),
("60", Ok(Value::String(""))),
("6161", Ok(Value::String("a"))),
("40", Ok(Value::Bytestring(&[]))),
("4100", Ok(Value::Bytestring(&[0x00]))),
("61ff", Err(Error::InvalidUtf8)),
("80", Ok(Value::Array(Vec::new()))),
("8101", Ok(Value::Array(vec![Value::Int(1)]))),
("818101", Ok(Value::Array(vec![Value::Array(vec![Value::Int(1)])]))),
(
"8181818181818181818181818181818181818180",
Err(Error::TooMuchNesting),
),
("a0", Ok(Value::Map(vec![].into()))),
("a10101", Ok(Value::Map(vec![(MapKey::Int(1), Value::Int(1)).into()].into()))),
("a12101", Ok(Value::Map(vec![(MapKey::Int(-2), Value::Int(1)).into()].into()))),
(
"a201010202",
Ok(Value::Map(
vec![
(MapKey::Int(1), Value::Int(1)).into(),
(MapKey::Int(2), Value::Int(2)).into(),
]
.into(),
)),
),
(
"a1410a01",
Ok(Value::Map(
vec![(
MapKey::Bytestring(&[0x0a]),
Value::Int(1),
).into()]
.into(),
)),
),
// This is a COSE key to check that map ordering works correctly.
(
"a501020326200121582009ac4af6a4646b5bfe81c37f751769c768c5c41ffea633dad0f48e6e3bc3e9a0225820269fbe132c40bf11f4de4a92bec527901906fdce98bbed52df9b175b6a4f3808",
Ok(Value::Map(
vec![
(MapKey::Int(1), Value::Int(2)).into(),
(MapKey::Int(3), Value::Int(-7)).into(),
(MapKey::Int(-1), Value::Int(1)).into(),
(
MapKey::Int(-2),
Value::Bytestring(
b"\x09\xac\x4a\xf6\xa4\x64\x6b\x5b\xfe\x81\xc3\x7f\x75\x17\x69\xc7\x68\xc5\xc4\x1f\xfe\xa6\x33\xda\xd0\xf4\x8e\x6e\x3b\xc3\xe9\xa0",
),
).into(),
(
MapKey::Int(-3),
Value::Bytestring(
b"\x26\x9f\xbe\x13\x2c\x40\xbf\x11\xf4\xde\x4a\x92\xbe\xc5\x27\x90\x19\x06\xfd\xce\x98\xbb\xed\x52\xdf\x9b\x17\x5b\x6a\x4f\x38\x08",
),
).into(),
]
.into(),
)),
),
(
"a101a101a101a101a101a101a101a101a101a101a101a101a101a101a101a101a101a101a101a0",
Err(Error::TooMuchNesting),
),
("a202010102", Err(Error::OutOfOrderKey)),
("a1810101", Err(Error::IncorrectMapKeyType)),
("f4", Ok(Value::Boolean(false))),
("f5", Ok(Value::Boolean(true))),
("f6", Ok(Value::Null)),
("f7", Ok(Value::Undefined)),
("a201010102", Err(Error::DuplicateKey)),
("f93c00", Err(Error::UnsupportedFloatingPointValue)),
("fa3f801000", Err(Error::UnsupportedFloatingPointValue)),
("fb3ff0000000000001", Err(Error::UnsupportedFloatingPointValue)),
];
for test in test_cases {
let bytes = hex::decode(test.0).unwrap();
let result = parse_bytes(&bytes);
assert_eq!(result, test.1, "{}", test.0);
if let Ok(value) = result {
let bytes2 = value.to_bytes();
assert_eq!(bytes, bytes2, "{}", test.0);
}
if !bytes.is_empty() {
// All truncations of the input should fail to parse.
for i in 0..bytes.len() - 1 {
let result = parse_bytes(&bytes[..i]);
assert!(result.is_err());
}
}
}
}
#[gtest(CBORReaderRustTest, TestCornerCases)]
fn test_corner_cases() {
let test_cases = [
// B. Defensive Memory Constraints (OOM / DOS Prevention)
("5bffffffffffffffff", Err(Error::IncompleteCborData)),
// C. Illegal / Indefinite Encodings
("5f", Err(Error::UnknownAdditionalInfo)),
("7f", Err(Error::UnknownAdditionalInfo)),
("9f", Err(Error::UnknownAdditionalInfo)),
("bf", Err(Error::UnknownAdditionalInfo)),
("ff", Err(Error::UnknownAdditionalInfo)),
// D. Advanced UTF-8 & Unicode Escapes
("62c080", Err(Error::InvalidUtf8)),
("63eda080", Err(Error::InvalidUtf8)),
("626100", Ok(Value::String("a\x00"))),
// E. Semantic CBOR Tags Rejection
("c0", Err(Error::UnsupportedMajorType)),
("c2", Err(Error::UnsupportedMajorType)),
];
for test in test_cases {
let bytes = hex::decode(test.0).unwrap();
let result = parse_bytes(&bytes);
assert_eq!(result, test.1, "{}", test.0);
}
}
#[gtest(CBORReaderRustTest, TestMapKeyIsUnsupportedSimpleValue)]
fn test_map_unsupported_simple_values() {
let bytes_key = hex::decode("a1f002").unwrap();
let result_key = parse_bytes(&bytes_key);
assert_eq!(result_key, Err(Error::UnsupportedSimpleValue));
let bytes_value = hex::decode("a102f0").unwrap();
let result_value = parse_bytes(&bytes_value);
assert_eq!(result_value, Err(Error::UnsupportedSimpleValue));
}