Skip to content

Commit 7be9d22

Browse files
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into chore/aac-early-return-error-consensus-tests
2 parents 96c9e01 + cf8d685 commit 7be9d22

File tree

117 files changed

+53014
-124
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+53014
-124
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"args": [
2828
"build",
2929
"--bin=clarity-cli",
30-
"--package=stackslib"
30+
"--package=clarity-cli"
3131
],
3232
"filter": {
3333
"name": "clarity-cli",

Cargo.lock

Lines changed: 61 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

clarity-types/src/errors/analysis.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,6 @@ pub enum CheckErrorKind {
480480
/// String contains invalid UTF-8 encoding.
481481
InvalidUTF8Encoding,
482482

483-
// secp256k1 signature
484-
/// Invalid secp256k1 signature provided in an expression.
485-
InvalidSecp65k1Signature,
486-
487483
/// Attempt to write to contract state in a read-only function.
488484
WriteAttemptedInReadOnly,
489485
/// `at-block` closure must be read-only but contains write operations.
@@ -814,7 +810,6 @@ impl DiagnosableError for CheckErrorKind {
814810
CheckErrorKind::TraitTooManyMethods(found, allowed) => format!("too many trait methods specified: found {found}, the maximum is {allowed}"),
815811
CheckErrorKind::InvalidCharactersDetected => "invalid characters detected".into(),
816812
CheckErrorKind::InvalidUTF8Encoding => "invalid UTF8 encoding".into(),
817-
CheckErrorKind::InvalidSecp65k1Signature => "invalid seckp256k1 signature".into(),
818813
CheckErrorKind::TypeAlreadyAnnotatedFailure | CheckErrorKind::CheckerImplementationFailure => {
819814
"internal error - please file an issue on https://github.com/stacks-network/stacks-blockchain".into()
820815
},

clarity-types/src/tests/types/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,46 @@ fn test_utf8_data_len_returns_vm_internal_error() {
585585
err
586586
);
587587
}
588+
589+
#[test]
590+
fn invalid_utf8_encoding_from_oob_unicode_escape() {
591+
// This is a syntactically valid escape: \u{HEX}
592+
// BUT 110000 > 10FFFF (max Unicode scalar)
593+
// So oob Unicode → char::from_u32(None) → InvalidUTF8Encoding
594+
let bad_utf8_literal = "\\u{110000}".to_string();
595+
596+
let err = Value::string_utf8_from_string_utf8_literal(bad_utf8_literal).unwrap_err();
597+
assert!(matches!(
598+
err,
599+
VmExecutionError::Unchecked(CheckErrorKind::InvalidUTF8Encoding)
600+
));
601+
}
602+
603+
#[test]
604+
fn invalid_string_ascii_from_bytes() {
605+
// 0xFF is NOT:
606+
// - ASCII alphanumeric
607+
// - ASCII punctuation
608+
// - ASCII whitespace
609+
let bad_bytes = vec![0xFF];
610+
611+
let err = Value::string_ascii_from_bytes(bad_bytes).unwrap_err();
612+
613+
assert!(matches!(
614+
err,
615+
VmExecutionError::Unchecked(CheckErrorKind::InvalidCharactersDetected)
616+
));
617+
}
618+
619+
#[test]
620+
fn invalid_utf8_string_from_bytes() {
621+
// 0x80 is an invalid standalone UTF-8 continuation byte
622+
let bad_bytes = vec![0x80];
623+
624+
let err = Value::string_utf8_from_bytes(bad_bytes).unwrap_err();
625+
626+
assert!(matches!(
627+
err,
628+
VmExecutionError::Unchecked(CheckErrorKind::InvalidCharactersDetected)
629+
));
630+
}

clarity-types/src/types/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,8 @@ impl Value {
10521052
.ok_or_else(|| VmInternalError::Expect("Expected capture".into()))?;
10531053
let scalar_value = window[matched.start()..matched.end()].to_string();
10541054
let unicode_char = {
1055+
// This first InvalidUTF8Encoding is logically unreachable: the escape regex rejects non-hex digits,
1056+
// so from_str_radix only sees valid hex and never errors here.
10551057
let u = u32::from_str_radix(&scalar_value, 16)
10561058
.map_err(|_| CheckErrorKind::InvalidUTF8Encoding)?;
10571059
let c = char::from_u32(u).ok_or_else(|| CheckErrorKind::InvalidUTF8Encoding)?;
@@ -1445,6 +1447,10 @@ impl PrincipalData {
14451447
literal: &str,
14461448
) -> Result<StandardPrincipalData, VmExecutionError> {
14471449
let (version, data) = c32::c32_address_decode(literal).map_err(|x| {
1450+
// This `TypeParseFailure` is unreachable in normal Clarity execution.
1451+
// - All principal literals are validated by the Clarity lexer *before* reaching `parse_standard_principal`.
1452+
// - The lexer rejects any literal containing characters outside the C32 alphabet.
1453+
// Therefore, only malformed input fed directly into low-level VM entry points can cause this branch to execute.
14481454
RuntimeError::TypeParseFailure(format!("Invalid principal literal: {x}"))
14491455
})?;
14501456
if data.len() != 20 {
@@ -1638,10 +1644,7 @@ impl TupleData {
16381644
})
16391645
}
16401646

1641-
pub fn shallow_merge(
1642-
mut base: TupleData,
1643-
updates: TupleData,
1644-
) -> Result<TupleData, VmExecutionError> {
1647+
pub fn shallow_merge(mut base: TupleData, updates: TupleData) -> TupleData {
16451648
let TupleData {
16461649
data_map,
16471650
mut type_signature,
@@ -1650,7 +1653,7 @@ impl TupleData {
16501653
base.data_map.insert(name, value);
16511654
}
16521655
base.type_signature.shallow_merge(&mut type_signature);
1653-
Ok(base)
1656+
base
16541657
}
16551658
}
16561659

0 commit comments

Comments
 (0)