Skip to content

Commit

Permalink
issue #914 -- enforce name legality at (define...)
Browse files Browse the repository at this point in the history
  • Loading branch information
kantai committed Feb 6, 2019
1 parent fe8e394 commit 02f15cb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
4 changes: 3 additions & 1 deletion blockstack-vm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ pub enum Error {
MaxStackDepthReached,
ListDimensionTooHigh,
ExpectedListPairs,
BadSymbolicRepresentation(String)
BadSymbolicRepresentation(String),
ReservedName(String),
MultiplyDefined(String)
}

pub type InterpreterResult <R> = Result<R, Error>;
Expand Down
24 changes: 24 additions & 0 deletions blockstack-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod errors;
pub mod database;

mod functions;
mod variables;

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


fn is_reserved(name: &str) -> bool {
if let Some(_result) = functions::lookup_reserved_functions(name) {
true
} else if variables::is_reserved_variable(name) {
true
} else {
false
}
}

fn check_legal_define(name: &str, context: &Context) -> Result<()> {
if is_reserved(name) {
Err(Error::ReservedName(name.to_string()))
} else if context.variables.contains_key(name) || context.functions.contains_key(name) {
Err(Error::MultiplyDefined(name.to_string()))
} else {
Ok(())
}
}

/* This function evaluates a list of expressions, sharing a global context.
* It returns the final evaluated result.
*/
Expand All @@ -113,12 +134,15 @@ fn eval_all(expressions: &[SymbolicExpression],
let try_define = functions::define::evaluate_define(exp, &mut env)?;
match try_define {
DefineResult::Variable(name, value) => {
check_legal_define(&name, &env.global_context)?;
env.global_context.variables.insert(name, value);
},
DefineResult::Function(name, value) => {
check_legal_define(&name, &env.global_context)?;
env.global_context.functions.insert(name, value);
},
DefineResult::Map(name, key_type, value_type) => {
check_legal_define(&name, &env.global_context)?;
env.database.create_map(&name, key_type, value_type);
},
DefineResult::NoDefine => {
Expand Down
24 changes: 24 additions & 0 deletions blockstack-vm/tests/defines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ fn test_defines() {
assert_eq!(Ok(Value::Int(1)), execute(&tests));
}

#[test]
fn test_bad_define_names() {
let test0 =
"(define tx-sender 1)
(+ tx-sender tx-sender)";
let test1 =
"(define * 1)
(+ * *)";
let test2 =
"(define 1 1)
(+ 1 1)";
let test3 =
"(define foo 1)
(define foo 2)
(+ foo foo)";

assert_eq!(Err(Error::ReservedName("tx-sender".to_string())), execute(&test0));
assert_eq!(Err(Error::ReservedName("*".to_string())), execute(&test1));
assert_eq!(Err(Error::InvalidArguments("Illegal operation: attempted to re-define a value type.".to_string())),
execute(&test2));
assert_eq!(Err(Error::MultiplyDefined("foo".to_string())),
execute(&test3));
}

#[test]
fn test_recursive_panic() {
let tests =
Expand Down

0 comments on commit 02f15cb

Please sign in to comment.