• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacks-network / stacks-core / 25903914664-1

15 May 2026 06:28AM UTC coverage: 47.122% (-38.8%) from 85.959%
25903914664-1

Pull #7199

github

94e391
web-flow
Merge 109f2828c into 1c7b8e6ac
Pull Request #7199: Feat: L1 and L2 early unlocks, updating signer

103343 of 219309 relevant lines covered (47.12%)

12880462.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.33
/clarity/src/vm/ast/stack_depth_checker.rs
1
// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation
2
// Copyright (C) 2020 Stacks Open Internet Foundation
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

17
use crate::vm::ast::errors::{ParseErrorKind, ParseResult};
18
use crate::vm::ast::types::{BuildASTPass, ContractAST};
19
use crate::vm::representations::PreSymbolicExpression;
20
use crate::vm::representations::PreSymbolicExpressionType::{List, Tuple};
21
use crate::vm::{ClarityVersion, max_call_stack_depth_for_epoch};
22

23
// allow  the AST to get deeper than the max call stack depth,
24
//    but not much deeper (things like tuples would increase the
25
//    AST depth, without impacting the stack depth).
26
const AST_CALL_STACK_DEPTH_BUFFER: u64 = 5;
27

28
/// Bundles related stack depth limits for parsing and AST checks.
29
#[derive(Clone, Copy, Debug)]
30
pub struct StackDepthLimits {
31
    max_call_stack_depth: u64,
32
    max_nesting_depth: u64,
33
}
34

35
impl StackDepthLimits {
36
    pub fn new(max_call_stack_depth: u64) -> Self {
33,062,976✔
37
        let max_nesting_depth = AST_CALL_STACK_DEPTH_BUFFER.saturating_add(max_call_stack_depth);
33,062,976✔
38
        Self {
33,062,976✔
39
            max_call_stack_depth,
33,062,976✔
40
            max_nesting_depth,
33,062,976✔
41
        }
33,062,976✔
42
    }
33,062,976✔
43

44
    pub fn no_limit() -> Self {
×
45
        Self {
×
46
            max_call_stack_depth: u64::MAX,
×
47
            max_nesting_depth: u64::MAX,
×
48
        }
×
49
    }
×
50

51
    pub fn for_epoch(epoch: stacks_common::types::StacksEpochId) -> Self {
33,062,976✔
52
        Self::new(max_call_stack_depth_for_epoch(epoch))
33,062,976✔
53
    }
33,062,976✔
54

55
    pub fn max_call_stack_depth(&self) -> u64 {
71,796✔
56
        self.max_call_stack_depth
71,796✔
57
    }
71,796✔
58

59
    pub fn max_nesting_depth(&self) -> u64 {
220,594,044✔
60
        self.max_nesting_depth
220,594,044✔
61
    }
220,594,044✔
62
}
63

64
fn check(
89,702,280✔
65
    args: &[PreSymbolicExpression],
89,702,280✔
66
    depth: u64,
89,702,280✔
67
    depth_limits: StackDepthLimits,
89,702,280✔
68
) -> ParseResult<()> {
89,702,280✔
69
    if depth >= depth_limits.max_nesting_depth() {
89,702,280✔
70
        return Err(ParseErrorKind::ExpressionStackDepthTooDeep {
×
71
            max_depth: depth_limits.max_call_stack_depth(),
×
72
        }
×
73
        .into());
×
74
    }
89,702,280✔
75
    for expression in args.iter() {
228,630,612✔
76
        match expression.pre_expr {
228,630,612✔
77
            List(ref exprs) => check(exprs, depth + 1, depth_limits),
78,681,300✔
78
            _ => {
79
                // Other symbolic expressions don't have depth
80
                //  impacts.
81
                Ok(())
149,949,312✔
82
            }
83
        }?;
×
84
    }
85
    Ok(())
89,702,280✔
86
}
89,702,280✔
87

88
pub struct StackDepthChecker;
89

90
impl BuildASTPass for StackDepthChecker {
91
    fn run_pass(
11,020,980✔
92
        contract_ast: &mut ContractAST,
11,020,980✔
93
        _version: ClarityVersion,
11,020,980✔
94
        epoch: stacks_common::types::StacksEpochId,
11,020,980✔
95
    ) -> ParseResult<()> {
11,020,980✔
96
        let depth_limits = StackDepthLimits::for_epoch(epoch);
11,020,980✔
97
        check(&contract_ast.pre_expressions, 0, depth_limits)
11,020,980✔
98
    }
11,020,980✔
99
}
100

101
fn check_vary(
98,426,652✔
102
    args: &[PreSymbolicExpression],
98,426,652✔
103
    depth: u64,
98,426,652✔
104
    depth_limits: StackDepthLimits,
98,426,652✔
105
) -> ParseResult<()> {
98,426,652✔
106
    if depth >= depth_limits.max_nesting_depth() {
98,426,652✔
107
        return Err(ParseErrorKind::VaryExpressionStackDepthTooDeep {
12✔
108
            max_depth: depth_limits.max_call_stack_depth(),
12✔
109
        }
12✔
110
        .into());
12✔
111
    }
98,426,640✔
112
    for expression in args.iter() {
266,242,260✔
113
        match expression.pre_expr {
266,242,260✔
114
            List(ref exprs) => check_vary(exprs, depth + 1, depth_limits),
82,476,372✔
115
            Tuple(ref exprs) => check_vary(exprs, depth + 1, depth_limits),
4,929,300✔
116
            _ => {
117
                // Other symbolic expressions don't have depth
118
                //  impacts.
119
                Ok(())
178,836,588✔
120
            }
121
        }?;
828✔
122
    }
123
    Ok(())
98,425,812✔
124
}
98,426,652✔
125

126
pub struct VaryStackDepthChecker;
127

128
impl BuildASTPass for VaryStackDepthChecker {
129
    fn run_pass(
11,020,980✔
130
        contract_ast: &mut ContractAST,
11,020,980✔
131
        _version: ClarityVersion,
11,020,980✔
132
        epoch: stacks_common::types::StacksEpochId,
11,020,980✔
133
    ) -> ParseResult<()> {
11,020,980✔
134
        let depth_limits = StackDepthLimits::for_epoch(epoch);
11,020,980✔
135
        check_vary(&contract_ast.pre_expressions, 0, depth_limits)
11,020,980✔
136
    }
11,020,980✔
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc