From 3d4a57d42ecf67d2a0e2fc6502e1be8e87d994b6 Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Thu, 6 Aug 2020 22:35:28 -0400 Subject: [PATCH] Forbid negative len --- src/vm/analysis/errors.rs | 2 ++ src/vm/analysis/type_checker/tests/mod.rs | 39 +++++++++++++++++++++++ src/vm/types/signatures.rs | 4 +++ 3 files changed, 45 insertions(+) diff --git a/src/vm/analysis/errors.rs b/src/vm/analysis/errors.rs index 699838cb8..34bd5ba7c 100644 --- a/src/vm/analysis/errors.rs +++ b/src/vm/analysis/errors.rs @@ -15,6 +15,7 @@ pub enum CheckErrors { MemoryBalanceExceeded(u64, u64), ValueTooLarge, + ValueOutOfBounds, TypeSignatureTooDeep, ExpectedName, @@ -290,6 +291,7 @@ impl DiagnosableError for CheckErrors { CheckErrors::BadSyntaxExpectedListOfPairs => "bad syntax: function expects a list of pairs to bind names, e.g., ((name-0 a) (name-1 b) ...)".into(), CheckErrors::UnknownTypeName(name) => format!("failed to parse type: '{}'", name), CheckErrors::ValueTooLarge => format!("created a type which was greater than maximum allowed value size"), + CheckErrors::ValueOutOfBounds => format!("created a type which value size was out of defined bounds"), CheckErrors::TypeSignatureTooDeep => "created a type which was deeper than maximum allowed type depth".into(), CheckErrors::ExpectedName => format!("expected a name argument to this function"), CheckErrors::NoSuperType(a, b) => format!("unable to create a supertype for the two types: '{}' and '{}'", a, b), diff --git a/src/vm/analysis/type_checker/tests/mod.rs b/src/vm/analysis/type_checker/tests/mod.rs index 703d52a2c..6a759f6a8 100644 --- a/src/vm/analysis/type_checker/tests/mod.rs +++ b/src/vm/analysis/type_checker/tests/mod.rs @@ -1798,3 +1798,42 @@ fn test_string_utf8_concat() { assert_eq!(expected, &format!("{}", type_check_helper(&good_test).unwrap())); } } + +#[test] +fn test_buff_negative_len() { + let contract_src = + "(define-private (func (x (buff -12))) (len x)) + (func 0x00)"; + + let res = mem_type_check(&contract_src).unwrap_err(); + assert!(match &res.err { + &CheckErrors::BadSyntaxBinding => true, + _ => false + }); +} + +#[test] +fn test_string_ascii_negative_len() { + let contract_src = + "(define-private (func (x (string-ascii -12))) (len x)) + (func \"\")"; + + let res = mem_type_check(&contract_src).unwrap_err(); + assert!(match &res.err { + &CheckErrors::BadSyntaxBinding => true, + _ => false + }); +} + +#[test] +fn test_string_utf8_negative_len() { + let contract_src = + "(define-private (func (x (string-utf8 -12))) (len x)) + (func u\"\")"; + + let res = mem_type_check(&contract_src).unwrap_err(); + assert!(match &res.err { + &CheckErrors::BadSyntaxBinding => true, + _ => false + }); +} diff --git a/src/vm/types/signatures.rs b/src/vm/types/signatures.rs index 43445ffd6..0a570d141 100644 --- a/src/vm/types/signatures.rs +++ b/src/vm/types/signatures.rs @@ -212,6 +212,8 @@ impl TryFrom for BufferLength { fn try_from(data: i128) -> Result { if data > (MAX_VALUE_SIZE as i128) { Err(CheckErrors::ValueTooLarge) + } else if data < 0 { + Err(CheckErrors::ValueOutOfBounds) } else { Ok(BufferLength(data as u32)) } @@ -257,6 +259,8 @@ impl TryFrom for StringUTF8Length { fn try_from(data: i128) -> Result { if data * 4 > (MAX_VALUE_SIZE as i128) { Err(CheckErrors::ValueTooLarge) + } else if data < 0 { + Err(CheckErrors::ValueOutOfBounds) } else { Ok(StringUTF8Length(data as u32)) }