Skip to content
970 changes: 815 additions & 155 deletions clarity-types/src/errors/analysis.rs

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions clarity-types/src/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod lexer;

use std::{error, fmt};

use analysis::CommonCheckErrorKind;
pub use analysis::{CheckErrorKind, StaticCheckError};
pub use ast::{ParseError, ParseErrorKind, ParseResult};
pub use cost::CostErrors;
Expand Down Expand Up @@ -296,15 +297,21 @@ impl From<RuntimeError> for VmExecutionError {
}
}

impl From<CommonCheckErrorKind> for VmExecutionError {
fn from(err: CommonCheckErrorKind) -> Self {
VmExecutionError::Unchecked(err.into())
}
}

impl From<CheckErrorKind> for VmExecutionError {
fn from(err: CheckErrorKind) -> Self {
VmExecutionError::Unchecked(err)
}
}

impl From<(CheckErrorKind, &SymbolicExpression)> for VmExecutionError {
fn from(err: (CheckErrorKind, &SymbolicExpression)) -> Self {
VmExecutionError::Unchecked(err.0)
impl From<(CommonCheckErrorKind, &SymbolicExpression)> for VmExecutionError {
fn from(err: (CommonCheckErrorKind, &SymbolicExpression)) -> Self {
VmExecutionError::Unchecked(err.0.into())
}
}

Expand Down
3 changes: 2 additions & 1 deletion clarity-types/src/tests/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rstest::rstest;
use stacks_common::types::StacksEpochId;

use crate::VmExecutionError;
use crate::errors::analysis::CommonCheckErrorKind;
use crate::errors::{CheckErrorKind, RuntimeError, VmInternalError};
use crate::types::{
ASCIIData, BuffData, CharType, ListTypeData, MAX_VALUE_SIZE, PrincipalData,
Expand All @@ -38,7 +39,7 @@ fn test_constructors() {
);
assert_eq!(
ListTypeData::new_list(TypeSignature::IntType, MAX_VALUE_SIZE),
Err(CheckErrorKind::ValueTooLarge)
Err(CommonCheckErrorKind::ValueTooLarge)
);

assert_eq!(
Expand Down
22 changes: 11 additions & 11 deletions clarity-types/src/tests/types/signatures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use std::collections::HashSet;

use crate::errors::CheckErrorKind;
use crate::errors::analysis::CommonCheckErrorKind;
use crate::representations::CONTRACT_MAX_NAME_LENGTH;
use crate::types::TypeSignature::{BoolType, IntType, ListUnionType, UIntType};
use crate::types::signatures::{CallableSubtype, TypeSignature};
Expand Down Expand Up @@ -43,7 +43,7 @@ fn test_buffer_length_try_from_u32_trait() {
assert_eq!(MAX_VALUE_SIZE, buffer.get_value());

let err = BufferLength::try_from(MAX_VALUE_SIZE + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);
}

#[test]
Expand All @@ -55,7 +55,7 @@ fn test_buffer_length_try_from_usize_trait() {
assert_eq!(MAX_VALUE_SIZE, buffer.get_value());

let err = BufferLength::try_from(MAX_VALUE_SIZE as usize + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);
}

#[test]
Expand All @@ -67,10 +67,10 @@ fn test_buffer_length_try_from_i128_trait() {
assert_eq!(MAX_VALUE_SIZE, buffer.get_value());

let err = BufferLength::try_from(MAX_VALUE_SIZE as i128 + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);

let err = BufferLength::try_from(-1_i128).unwrap_err();
assert_eq!(CheckErrorKind::ValueOutOfBounds, err);
assert_eq!(CommonCheckErrorKind::ValueOutOfBounds, err);
}

#[test]
Expand Down Expand Up @@ -229,7 +229,7 @@ fn test_string_utf8_length_try_from_u32_trait() {
assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value());

let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);
}

#[test]
Expand All @@ -244,7 +244,7 @@ fn test_string_utf8_length_try_from_usize_trait() {
assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value());

let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE as usize + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);
}

#[test]
Expand All @@ -259,10 +259,10 @@ fn test_string_utf8_length_try_from_i128_trait() {
assert_eq!(MAX_UTF8_VALUE_SIZE, string.get_value());

let err = StringUTF8Length::try_from(MAX_UTF8_VALUE_SIZE as i128 + 1).unwrap_err();
assert_eq!(CheckErrorKind::ValueTooLarge, err);
assert_eq!(CommonCheckErrorKind::ValueTooLarge, err);

let err = StringUTF8Length::try_from(-1_i128).unwrap_err();
assert_eq!(CheckErrorKind::ValueOutOfBounds, err);
assert_eq!(CommonCheckErrorKind::ValueOutOfBounds, err);
}

#[test]
Expand Down Expand Up @@ -826,11 +826,11 @@ fn test_least_supertype() {
for pair in bad_pairs {
matches!(
TypeSignature::least_supertype_v2_1(&pair.0, &pair.1).unwrap_err(),
CheckErrorKind::TypeError(..)
CommonCheckErrorKind::TypeError(..)
);
matches!(
TypeSignature::least_supertype_v2_1(&pair.1, &pair.0).unwrap_err(),
CheckErrorKind::TypeError(..)
CommonCheckErrorKind::TypeError(..)
);
}
}
31 changes: 19 additions & 12 deletions clarity-types/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub use self::signatures::{
AssetIdentifier, BufferLength, ListTypeData, SequenceSubtype, StringSubtype, StringUTF8Length,
TupleTypeSignature, TypeSignature,
};
use crate::errors::analysis::CommonCheckErrorKind;
use crate::errors::{CheckErrorKind, InterpreterResult as Result, RuntimeError, VmInternalError};
use crate::representations::{ClarityName, ContractName, SymbolicExpression};

Expand Down Expand Up @@ -700,7 +701,7 @@ impl fmt::Display for UTF8Data {
}

pub trait SequencedValue<T> {
fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind>;
fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind>;

fn items(&self) -> &Vec<T>;

Expand All @@ -725,7 +726,7 @@ impl SequencedValue<Value> for ListData {
self.data.drain(..).collect()
}

fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
Ok(TypeSignature::SequenceType(SequenceSubtype::ListType(
self.type_signature.clone(),
)))
Expand All @@ -745,9 +746,11 @@ impl SequencedValue<u8> for BuffData {
self.data.drain(..).collect()
}

fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
let buff_length = BufferLength::try_from(self.data.len()).map_err(|_| {
CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into())
CommonCheckErrorKind::Expects(
"ERROR: Too large of a buffer successfully constructed.".into(),
)
})?;
Ok(TypeSignature::SequenceType(SequenceSubtype::BufferType(
buff_length,
Expand All @@ -768,9 +771,11 @@ impl SequencedValue<u8> for ASCIIData {
self.data.drain(..).collect()
}

fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
let buff_length = BufferLength::try_from(self.data.len()).map_err(|_| {
CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into())
CommonCheckErrorKind::Expects(
"ERROR: Too large of a buffer successfully constructed.".into(),
)
})?;
Ok(TypeSignature::SequenceType(SequenceSubtype::StringType(
StringSubtype::ASCII(buff_length),
Expand All @@ -794,9 +799,11 @@ impl SequencedValue<Vec<u8>> for UTF8Data {
self.data.drain(..).collect()
}

fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
let str_len = StringUTF8Length::try_from(self.data.len()).map_err(|_| {
CheckErrorKind::Expects("ERROR: Too large of a buffer successfully constructed.".into())
CommonCheckErrorKind::Expects(
"ERROR: Too large of a buffer successfully constructed.".into(),
)
})?;
Ok(TypeSignature::SequenceType(SequenceSubtype::StringType(
StringSubtype::UTF8(str_len),
Expand All @@ -812,19 +819,19 @@ impl SequencedValue<Vec<u8>> for UTF8Data {
}

impl OptionalData {
pub fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
pub fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
let type_result = match self.data {
Some(ref v) => TypeSignature::new_option(TypeSignature::type_of(v)?),
None => TypeSignature::new_option(TypeSignature::NoType),
};
type_result.map_err(|_| {
CheckErrorKind::Expects("Should not have constructed too large of a type.".into())
CommonCheckErrorKind::Expects("Should not have constructed too large of a type.".into())
})
}
}

impl ResponseData {
pub fn type_signature(&self) -> std::result::Result<TypeSignature, CheckErrorKind> {
pub fn type_signature(&self) -> std::result::Result<TypeSignature, CommonCheckErrorKind> {
let type_result = match self.committed {
true => TypeSignature::new_response(
TypeSignature::type_of(&self.data)?,
Expand All @@ -836,7 +843,7 @@ impl ResponseData {
),
};
type_result.map_err(|_| {
CheckErrorKind::Expects("Should not have constructed too large of a type.".into())
CommonCheckErrorKind::Expects("Should not have constructed too large of a type.".into())
})
}
}
Expand Down
39 changes: 21 additions & 18 deletions clarity-types/src/types/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use stacks_common::util::hash::{hex_bytes, to_hex};
use stacks_common::util::retry::BoundReader;

use super::{ListTypeData, TupleTypeSignature};
use crate::errors::analysis::StaticCheckErrorKind;
use crate::errors::{CheckErrorKind, IncomparableError, VmInternalError};
use crate::representations::{ClarityName, ContractName, MAX_STRING_LEN};
use crate::types::{
Expand Down Expand Up @@ -394,7 +395,7 @@ impl TypeSignature {
/// size of a `(buff 1024*1024)` is `1+1024*1024` because of the
/// type prefix byte. However, that is 1 byte larger than the maximum
/// buffer size in Clarity.
pub fn max_serialized_size(&self) -> Result<u32, CheckErrorKind> {
pub fn max_serialized_size(&self) -> Result<u32, StaticCheckErrorKind> {
let type_prefix_size = 1;

let max_output_size = match self {
Expand All @@ -405,7 +406,7 @@ impl TypeSignature {
// `some` or similar with `result` types). So, when
// serializing an object with a `NoType`, the other
// branch should always be used.
return Err(CheckErrorKind::CouldNotDetermineSerializationType);
return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType);
}
TypeSignature::IntType => 16,
TypeSignature::UIntType => 16,
Expand All @@ -417,14 +418,14 @@ impl TypeSignature {
.get_max_len()
.checked_mul(list_type.get_list_item_type().max_serialized_size()?)
.and_then(|x| x.checked_add(list_length_encode))
.ok_or_else(|| CheckErrorKind::ValueTooLarge)?
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?
}
TypeSignature::SequenceType(SequenceSubtype::BufferType(buff_length)) => {
// u32 length as big-endian bytes
let buff_length_encode = 4;
u32::from(buff_length)
.checked_add(buff_length_encode)
.ok_or_else(|| CheckErrorKind::ValueTooLarge)?
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?
}
TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII(
length,
Expand All @@ -434,7 +435,7 @@ impl TypeSignature {
// ascii is 1-byte per character
u32::from(length)
.checked_add(str_length_encode)
.ok_or_else(|| CheckErrorKind::ValueTooLarge)?
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?
}
TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8(
length,
Expand All @@ -445,7 +446,7 @@ impl TypeSignature {
u32::from(length)
.checked_mul(4)
.and_then(|x| x.checked_add(str_length_encode))
.ok_or_else(|| CheckErrorKind::ValueTooLarge)?
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?
}
TypeSignature::PrincipalType
| TypeSignature::CallableType(_)
Expand All @@ -468,7 +469,7 @@ impl TypeSignature {
.checked_add(1) // length of key-name
.and_then(|x| x.checked_add(key.len() as u32)) // ClarityName is ascii-only, so 1 byte per length
.and_then(|x| x.checked_add(value_size))
.ok_or_else(|| CheckErrorKind::ValueTooLarge)?;
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)?;
}
total_size
}
Expand All @@ -477,25 +478,25 @@ impl TypeSignature {
Ok(size) => size,
// if NoType, then this is just serializing a none
// value, which is only the type prefix
Err(CheckErrorKind::CouldNotDetermineSerializationType) => 0,
Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => 0,
Err(e) => return Err(e),
}
}
TypeSignature::ResponseType(response_types) => {
let (ok_type, err_type) = response_types.as_ref();
let (ok_type_max_size, no_ok_type) = match ok_type.max_serialized_size() {
Ok(size) => (size, false),
Err(CheckErrorKind::CouldNotDetermineSerializationType) => (0, true),
Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => (0, true),
Err(e) => return Err(e),
};
let err_type_max_size = match err_type.max_serialized_size() {
Ok(size) => size,
Err(CheckErrorKind::CouldNotDetermineSerializationType) => {
Err(StaticCheckErrorKind::CouldNotDetermineSerializationType) => {
if no_ok_type {
// if both the ok type and the error type are NoType,
// throw a CheckErrorKind. This should not be possible, but the check
// throw a StaticCheckErrorKind. This should not be possible, but the check
// is done out of caution.
return Err(CheckErrorKind::CouldNotDetermineSerializationType);
return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType);
} else {
0
}
Expand All @@ -505,13 +506,13 @@ impl TypeSignature {
cmp::max(ok_type_max_size, err_type_max_size)
}
TypeSignature::ListUnionType(_) => {
return Err(CheckErrorKind::CouldNotDetermineSerializationType);
return Err(StaticCheckErrorKind::CouldNotDetermineSerializationType);
}
};

max_output_size
.checked_add(type_prefix_size)
.ok_or_else(|| CheckErrorKind::ValueTooLarge)
.ok_or_else(|| StaticCheckErrorKind::ValueTooLarge)
}
}

Expand Down Expand Up @@ -612,8 +613,8 @@ impl Value {
TypePrefix::Buffer => {
let mut buffer_len = [0; 4];
r.read_exact(&mut buffer_len)?;
let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))?;

let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))
.map_err(CheckErrorKind::from)?;
if let Some(x) = &expected_type {
let passed_test = match x {
TypeSignature::SequenceType(SequenceSubtype::BufferType(
Expand Down Expand Up @@ -844,7 +845,8 @@ impl Value {
TypePrefix::StringASCII => {
let mut buffer_len = [0; 4];
r.read_exact(&mut buffer_len)?;
let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))?;
let buffer_len = BufferLength::try_from(u32::from_be_bytes(buffer_len))
.map_err(CheckErrorKind::from)?;

if let Some(x) = &expected_type {
let passed_test = match x {
Expand All @@ -869,7 +871,8 @@ impl Value {
TypePrefix::StringUTF8 => {
let mut total_len = [0; 4];
r.read_exact(&mut total_len)?;
let total_len = BufferLength::try_from(u32::from_be_bytes(total_len))?;
let total_len = BufferLength::try_from(u32::from_be_bytes(total_len))
.map_err(CheckErrorKind::from)?;

let mut data: Vec<u8> = vec![0; u32::from(total_len) as usize];

Expand Down
Loading
Loading