Skip to content

Commit 02f15cb

Browse files
committed
issue #914 -- enforce name legality at (define...)
1 parent fe8e394 commit 02f15cb

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

blockstack-vm/src/errors.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ pub enum Error {
1616
MaxStackDepthReached,
1717
ListDimensionTooHigh,
1818
ExpectedListPairs,
19-
BadSymbolicRepresentation(String)
19+
BadSymbolicRepresentation(String),
20+
ReservedName(String),
21+
MultiplyDefined(String)
2022
}
2123

2224
pub type InterpreterResult <R> = Result<R, Error>;

blockstack-vm/src/lib.rs

+24
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod errors;
88
pub mod database;
99

1010
mod functions;
11+
mod variables;
1112

1213
use types::{Value, CallableType};
1314
use representations::SymbolicExpression;
@@ -100,6 +101,26 @@ pub fn eval <'a> (exp: &SymbolicExpression, env: &'a mut Environment, context: &
100101
}
101102

102103

104+
fn is_reserved(name: &str) -> bool {
105+
if let Some(_result) = functions::lookup_reserved_functions(name) {
106+
true
107+
} else if variables::is_reserved_variable(name) {
108+
true
109+
} else {
110+
false
111+
}
112+
}
113+
114+
fn check_legal_define(name: &str, context: &Context) -> Result<()> {
115+
if is_reserved(name) {
116+
Err(Error::ReservedName(name.to_string()))
117+
} else if context.variables.contains_key(name) || context.functions.contains_key(name) {
118+
Err(Error::MultiplyDefined(name.to_string()))
119+
} else {
120+
Ok(())
121+
}
122+
}
123+
103124
/* This function evaluates a list of expressions, sharing a global context.
104125
* It returns the final evaluated result.
105126
*/
@@ -113,12 +134,15 @@ fn eval_all(expressions: &[SymbolicExpression],
113134
let try_define = functions::define::evaluate_define(exp, &mut env)?;
114135
match try_define {
115136
DefineResult::Variable(name, value) => {
137+
check_legal_define(&name, &env.global_context)?;
116138
env.global_context.variables.insert(name, value);
117139
},
118140
DefineResult::Function(name, value) => {
141+
check_legal_define(&name, &env.global_context)?;
119142
env.global_context.functions.insert(name, value);
120143
},
121144
DefineResult::Map(name, key_type, value_type) => {
145+
check_legal_define(&name, &env.global_context)?;
122146
env.database.create_map(&name, key_type, value_type);
123147
},
124148
DefineResult::NoDefine => {

blockstack-vm/tests/defines.rs

+24
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,30 @@ fn test_defines() {
2121
assert_eq!(Ok(Value::Int(1)), execute(&tests));
2222
}
2323

24+
#[test]
25+
fn test_bad_define_names() {
26+
let test0 =
27+
"(define tx-sender 1)
28+
(+ tx-sender tx-sender)";
29+
let test1 =
30+
"(define * 1)
31+
(+ * *)";
32+
let test2 =
33+
"(define 1 1)
34+
(+ 1 1)";
35+
let test3 =
36+
"(define foo 1)
37+
(define foo 2)
38+
(+ foo foo)";
39+
40+
assert_eq!(Err(Error::ReservedName("tx-sender".to_string())), execute(&test0));
41+
assert_eq!(Err(Error::ReservedName("*".to_string())), execute(&test1));
42+
assert_eq!(Err(Error::InvalidArguments("Illegal operation: attempted to re-define a value type.".to_string())),
43+
execute(&test2));
44+
assert_eq!(Err(Error::MultiplyDefined("foo".to_string())),
45+
execute(&test3));
46+
}
47+
2448
#[test]
2549
fn test_recursive_panic() {
2650
let tests =

0 commit comments

Comments
 (0)