mirror of
https://github.com/mii443/gpsl.git
synced 2025-12-03 11:08:27 +00:00
add security
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use gpsl::{
|
use gpsl::{
|
||||||
gpsl::GPSL,
|
vm::gpsl::GPSL,
|
||||||
source::Source,
|
source::Source,
|
||||||
std::*,
|
external_function::*,
|
||||||
tokenizer::Tokenizer,
|
tokenizer::Tokenizer,
|
||||||
parser::Parser
|
parser::Parser
|
||||||
};
|
};
|
||||||
@@ -14,7 +14,7 @@ fn main() {
|
|||||||
let mut source = Source::new(fs::read_to_string(&(args.last().unwrap())).expect("Cannot read file."));
|
let mut source = Source::new(fs::read_to_string(&(args.last().unwrap())).expect("Cannot read file."));
|
||||||
|
|
||||||
let mut tokenizer = Tokenizer::new();
|
let mut tokenizer = Tokenizer::new();
|
||||||
tokenizer.tokenize(&mut source);
|
tokenizer.tokenize(&mut source).unwrap();
|
||||||
|
|
||||||
let mut parser = Parser {
|
let mut parser = Parser {
|
||||||
tokenizer,
|
tokenizer,
|
||||||
|
|||||||
19
src/bin/test.rs
Normal file
19
src/bin/test.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("testing binary");
|
||||||
|
|
||||||
|
let mut queue: VecDeque<i64> = VecDeque::new();
|
||||||
|
|
||||||
|
queue.push_back(1i64);
|
||||||
|
queue.push_back(2i64);
|
||||||
|
queue.push_back(3i64);
|
||||||
|
|
||||||
|
for x in 0..queue.len() {
|
||||||
|
println!("{}", queue[x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{:?}", queue);
|
||||||
|
println!("{:?}", queue.len());
|
||||||
|
}
|
||||||
63
src/external_function.rs
Normal file
63
src/external_function.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::{variable::Variable, permission::Permission};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum ExternalFuncStatus {
|
||||||
|
SUCCESS,
|
||||||
|
NOTFOUND,
|
||||||
|
ERROR,
|
||||||
|
REJECTED,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ExternalFuncReturn {
|
||||||
|
pub status: ExternalFuncStatus,
|
||||||
|
pub value: Option<Variable>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const STD_FUNC: fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn = |name, args, accept, reject| {
|
||||||
|
let name = name.as_str();
|
||||||
|
match name {
|
||||||
|
"println" => {
|
||||||
|
if accept.contains(&Permission::StdIo) && !reject.contains(&Permission::StdIo) {
|
||||||
|
match &args[0] {
|
||||||
|
Variable::Text { value } => println!("{}", value),
|
||||||
|
Variable::Number { value } => println!("{}", value),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
ExternalFuncReturn {
|
||||||
|
status: ExternalFuncStatus::SUCCESS,
|
||||||
|
value: None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ExternalFuncReturn {
|
||||||
|
status: ExternalFuncStatus::REJECTED,
|
||||||
|
value: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"print" => {
|
||||||
|
if accept.contains(&Permission::StdIo) && !reject.contains(&Permission::StdIo) {
|
||||||
|
match &args[0] {
|
||||||
|
Variable::Text { value } => print!("{}", value),
|
||||||
|
Variable::Number { value } => print!("{}", value),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
ExternalFuncReturn {
|
||||||
|
status: ExternalFuncStatus::SUCCESS,
|
||||||
|
value: None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ExternalFuncReturn {
|
||||||
|
status: ExternalFuncStatus::REJECTED,
|
||||||
|
value: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
ExternalFuncReturn {
|
||||||
|
status: ExternalFuncStatus::NOTFOUND,
|
||||||
|
value: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -5,6 +5,7 @@ WS
|
|||||||
-> skip
|
-> skip
|
||||||
;
|
;
|
||||||
|
|
||||||
|
DOLLER: '$' ;
|
||||||
ADD: '+' ;
|
ADD: '+' ;
|
||||||
SUB: '-' ;
|
SUB: '-' ;
|
||||||
MUL: '*' ;
|
MUL: '*' ;
|
||||||
@@ -31,6 +32,8 @@ LPAREN: '(' ;
|
|||||||
RPAREN: ')' ;
|
RPAREN: ')' ;
|
||||||
LCURL: '{' ;
|
LCURL: '{' ;
|
||||||
RCURL: '}' ;
|
RCURL: '}' ;
|
||||||
|
LBRACKET: '[' ;
|
||||||
|
RBRACKET: ']' ;
|
||||||
ARROW: '->' ;
|
ARROW: '->' ;
|
||||||
|
|
||||||
FN: 'fn' ;
|
FN: 'fn' ;
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ stmt: let
|
|||||||
;
|
;
|
||||||
|
|
||||||
let: LET IDENT COLON IDENT SEMICOLON ;
|
let: LET IDENT COLON IDENT SEMICOLON ;
|
||||||
block: LCURL stmt* RCURL ;
|
block: permission? LCURL stmt* RCURL ;
|
||||||
return: RETURN expr? SEMICOLON ;
|
return: RETURN expr? SEMICOLON ;
|
||||||
if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ;
|
if: IF LPAREN expr RPAREN stmt (ELSE stmt)? ;
|
||||||
while: WHILE LPAREN expr RPAREN stmt ;
|
while: WHILE LPAREN expr RPAREN stmt ;
|
||||||
for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ;
|
for: FOR LPAREN expr? SEMICOLON expr? SEMICOLON expr? RPAREN stmt ;
|
||||||
|
|
||||||
|
permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ;
|
||||||
|
|
||||||
expr: assign ;
|
expr: assign ;
|
||||||
assign: equality (EQ assign)? ;
|
assign: equality (EQ assign)? ;
|
||||||
equality: relational (EQEQ relational | NE relational | CONJ)* ;
|
equality: relational (EQEQ relational | NE relational | CONJ)* ;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod gpsl;
|
pub mod vm;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
pub mod tokenizer;
|
pub mod tokenizer;
|
||||||
pub mod variable;
|
pub mod variable;
|
||||||
pub mod std;
|
pub mod external_function;
|
||||||
|
pub mod permission;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
@@ -20,6 +20,10 @@ pub enum Node {
|
|||||||
args: HashMap<String, String>,
|
args: HashMap<String, String>,
|
||||||
body: Vec<Box<Node>>
|
body: Vec<Box<Node>>
|
||||||
},
|
},
|
||||||
|
Permission {
|
||||||
|
accept: Vec<String>,
|
||||||
|
reject: Vec<String>
|
||||||
|
},
|
||||||
Operator {
|
Operator {
|
||||||
kind: NodeKind,
|
kind: NodeKind,
|
||||||
lhs: Box<Node>,
|
lhs: Box<Node>,
|
||||||
@@ -54,6 +58,7 @@ pub enum Node {
|
|||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
stmts: Vec<Box<Node>>,
|
stmts: Vec<Box<Node>>,
|
||||||
|
permission: Option<Box<Node>>
|
||||||
},
|
},
|
||||||
Define {
|
Define {
|
||||||
name: String,
|
name: String,
|
||||||
@@ -62,7 +67,8 @@ pub enum Node {
|
|||||||
Call {
|
Call {
|
||||||
name: String,
|
name: String,
|
||||||
args: Vec<Box<Node>>,
|
args: Vec<Box<Node>>,
|
||||||
}
|
},
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
|||||||
@@ -10,11 +10,14 @@ pub struct Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn functions(&mut self) -> Result<Vec<Box<Node>>, String> {
|
pub fn functions(&mut self) -> Result<HashMap<String, Box<Node>>, String> {
|
||||||
let mut nodes: Vec<Box<Node>> = vec![];
|
let mut nodes: HashMap<String, Box<Node>> = HashMap::new();
|
||||||
loop {
|
loop {
|
||||||
if self.tokenizer.current_token().kind != TokenKind::EOF {
|
if self.tokenizer.current_token().kind != TokenKind::EOF {
|
||||||
nodes.push(self.function()?);
|
let function = self.function()?;
|
||||||
|
if let Node::Function{name, .. } = *function.clone() {
|
||||||
|
nodes.insert(name, function);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(nodes);
|
return Ok(nodes);
|
||||||
}
|
}
|
||||||
@@ -40,6 +43,7 @@ impl Parser {
|
|||||||
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||||
args.insert(name, type_str);
|
args.insert(name, type_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut nodes: Vec<Box<Node>> = vec![];
|
let mut nodes: Vec<Box<Node>> = vec![];
|
||||||
debug!("parsing body node");
|
debug!("parsing body node");
|
||||||
loop {
|
loop {
|
||||||
@@ -99,9 +103,16 @@ impl Parser {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("parsing permission");
|
||||||
|
let permission = if self.tokenizer.current_token().str == "$" {
|
||||||
|
Some(self.permission()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.tokenizer
|
.tokenizer
|
||||||
.consume_kind_str(TokenKind::RESERVED, String::from("{"))
|
.consume_kind_str(TokenKind::RESERVED, String::from("{")) || permission != None
|
||||||
{
|
{
|
||||||
let mut stmts: Vec<Box<Node>> = vec![];
|
let mut stmts: Vec<Box<Node>> = vec![];
|
||||||
loop {
|
loop {
|
||||||
@@ -109,7 +120,7 @@ impl Parser {
|
|||||||
.tokenizer
|
.tokenizer
|
||||||
.consume_kind_str(TokenKind::RESERVED, String::from("}"))
|
.consume_kind_str(TokenKind::RESERVED, String::from("}"))
|
||||||
{
|
{
|
||||||
return Ok(Box::new(Node::Block { stmts }));
|
return Ok(Box::new(Node::Block { stmts, permission: permission }));
|
||||||
} else {
|
} else {
|
||||||
stmts.push(self.stmt()?);
|
stmts.push(self.stmt()?);
|
||||||
}
|
}
|
||||||
@@ -196,6 +207,39 @@ impl Parser {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
permission: DOLLER LPAREN ( IDENT LBRACKET ( IDENT COMMA? )* RBRACKET COMMA? )* RPAREN ;
|
||||||
|
*/
|
||||||
|
pub fn permission(&mut self) -> Result<Box<Node>, String> {
|
||||||
|
self.tokenizer.expect(String::from("$"))?;
|
||||||
|
self.tokenizer.expect(String::from("("))?;
|
||||||
|
|
||||||
|
let mut accept: Vec<String> = vec![];
|
||||||
|
let mut reject: Vec<String> = vec![];
|
||||||
|
|
||||||
|
while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(")")) {
|
||||||
|
let name = self.tokenizer.expect_ident()?;
|
||||||
|
if name != "accept" && name != "reject" {
|
||||||
|
return Err(String::from(format!("Unexpected: {}", name)));
|
||||||
|
}
|
||||||
|
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("["));
|
||||||
|
while !self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from("]")) {
|
||||||
|
let permission = self.tokenizer.expect_ident()?;
|
||||||
|
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||||
|
|
||||||
|
if name == "accept" {
|
||||||
|
accept.push(permission);
|
||||||
|
} else if name == "reject" {
|
||||||
|
reject.push(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tokenizer.consume_kind_str(TokenKind::RESERVED, String::from(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Box::new(Node::Permission { accept, reject }))
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
expr: assign ;
|
expr: assign ;
|
||||||
*/
|
*/
|
||||||
|
|||||||
16
src/permission.rs
Normal file
16
src/permission.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum Permission {
|
||||||
|
Administrator,
|
||||||
|
StdIo
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Permission {
|
||||||
|
pub fn from_string(permission: &str) -> Self {
|
||||||
|
match permission {
|
||||||
|
"Administrator" => Self::Administrator,
|
||||||
|
"StdIo" => Self::StdIo,
|
||||||
|
_ => panic!("Permission not found.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/std.rs
37
src/std.rs
@@ -1,37 +0,0 @@
|
|||||||
use crate::variable::Variable;
|
|
||||||
use crate::gpsl::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub const STD_FUNC: fn(String, Vec<Variable>) -> ExternalFuncReturn = |name, args| {
|
|
||||||
let name = name.as_str();
|
|
||||||
match name {
|
|
||||||
"println" => {
|
|
||||||
match &args[0] {
|
|
||||||
Variable::Text { value } => println!("{}", value),
|
|
||||||
Variable::Number { value } => println!("{}", value),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
ExternalFuncReturn {
|
|
||||||
status: ExternalFuncStatus::SUCCESS,
|
|
||||||
value: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"print" => {
|
|
||||||
match &args[0] {
|
|
||||||
Variable::Text { value } => print!("{}", value),
|
|
||||||
Variable::Number { value } => print!("{}", value),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
ExternalFuncReturn {
|
|
||||||
status: ExternalFuncStatus::SUCCESS,
|
|
||||||
value: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ExternalFuncReturn {
|
|
||||||
status: ExternalFuncStatus::NOTFOUND,
|
|
||||||
value: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -113,6 +113,7 @@ impl Tokenizer {
|
|||||||
String::from("-="),
|
String::from("-="),
|
||||||
String::from("*="),
|
String::from("*="),
|
||||||
String::from("/="),
|
String::from("/="),
|
||||||
|
String::from("$"),
|
||||||
String::from("+"),
|
String::from("+"),
|
||||||
String::from("-"),
|
String::from("-"),
|
||||||
String::from("*"),
|
String::from("*"),
|
||||||
@@ -123,6 +124,8 @@ impl Tokenizer {
|
|||||||
String::from("}"),
|
String::from("}"),
|
||||||
String::from("("),
|
String::from("("),
|
||||||
String::from(")"),
|
String::from(")"),
|
||||||
|
String::from("["),
|
||||||
|
String::from("]"),
|
||||||
String::from("=="),
|
String::from("=="),
|
||||||
String::from("!="),
|
String::from("!="),
|
||||||
String::from(">="),
|
String::from(">="),
|
||||||
@@ -152,7 +155,7 @@ impl Tokenizer {
|
|||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(_) => String::from(""),
|
Err(_) => String::from(""),
|
||||||
};
|
};
|
||||||
source.get_char(is('"'));
|
source.get_char(is('"'))?;
|
||||||
self.tokens.push(Token {
|
self.tokens.push(Token {
|
||||||
kind: TokenKind::TEXT,
|
kind: TokenKind::TEXT,
|
||||||
str: text,
|
str: text,
|
||||||
|
|||||||
@@ -1,38 +1,35 @@
|
|||||||
|
use crate::external_function::{ExternalFuncReturn, ExternalFuncStatus};
|
||||||
use crate::node::*;
|
use crate::node::*;
|
||||||
use crate::parser::*;
|
use crate::permission::Permission;
|
||||||
use crate::source::Source;
|
use crate::source::Source;
|
||||||
use crate::tokenizer::*;
|
|
||||||
use crate::variable::*;
|
use crate::variable::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::string::*;
|
use std::string::*;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ExternalFuncStatus {
|
pub struct Block {
|
||||||
SUCCESS,
|
pub accept: Vec<Permission>,
|
||||||
NOTFOUND,
|
pub reject: Vec<Permission>,
|
||||||
ERROR,
|
pub variables: HashMap<String, LocalVariable>,
|
||||||
}
|
pub is_split: bool
|
||||||
|
|
||||||
pub struct ExternalFuncReturn {
|
|
||||||
pub status: ExternalFuncStatus,
|
|
||||||
pub value: Option<Variable>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GPSL {
|
pub struct GPSL {
|
||||||
pub functions: Option<Vec<Box<Node>>>,
|
pub functions: Option<HashMap<String, Box<Node>>>,
|
||||||
pub global_variables: Vec<Variable>,
|
pub global_variables: Vec<Variable>,
|
||||||
pub source: Source,
|
pub source: Source,
|
||||||
pub l_vars: HashMap<String, LocalVariable>,
|
pub blocks: VecDeque<Block>,
|
||||||
pub external_func: Vec<fn(String, Vec<Variable>) -> ExternalFuncReturn>
|
pub external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct LocalVariable {
|
pub struct LocalVariable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: Variable,
|
pub value: Variable,
|
||||||
pub status: VariableStatus,
|
pub status: VariableStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct VariableStatus {
|
pub struct VariableStatus {
|
||||||
pub initialized: bool,
|
pub initialized: bool,
|
||||||
}
|
}
|
||||||
@@ -44,16 +41,46 @@ impl VariableStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GPSL {
|
impl GPSL {
|
||||||
pub fn new(source: Source, functions: Option<Vec<Box<Node>>>, external_func: Vec<fn(String, Vec<Variable>) -> ExternalFuncReturn>) -> GPSL {
|
pub fn new(source: Source, functions: Option<HashMap<String, Box<Node>>>, external_func: Vec<fn(String, Vec<Variable>, Vec<Permission>, Vec<Permission>) -> ExternalFuncReturn>) -> GPSL {
|
||||||
GPSL {
|
GPSL {
|
||||||
source,
|
source,
|
||||||
functions,
|
functions,
|
||||||
global_variables: vec![],
|
global_variables: vec![],
|
||||||
l_vars: HashMap::new(),
|
blocks: VecDeque::new(),
|
||||||
external_func
|
external_func
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_local_var_mut(&mut self, name: &String) -> Option<&mut LocalVariable> {
|
||||||
|
for x in 0..self.blocks.len() {
|
||||||
|
if self.blocks[x].variables.contains_key(name) {
|
||||||
|
return self.blocks[x].variables.get_mut(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.blocks[x].is_split {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_local_var(&mut self, name: &String) -> Option<LocalVariable> {
|
||||||
|
for x in 0..self.blocks.len() {
|
||||||
|
if self.blocks[x].variables.contains_key(name) {
|
||||||
|
if let Some(var) = self.blocks[x].variables.get(name).clone() {
|
||||||
|
return Some(var.clone());
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.blocks[x].is_split {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extract_number(node: Variable) -> Result<usize, String> {
|
pub fn extract_number(node: Variable) -> Result<usize, String> {
|
||||||
match node {
|
match node {
|
||||||
Variable::Number { value } => {
|
Variable::Number { value } => {
|
||||||
@@ -78,33 +105,54 @@ impl GPSL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(functions) = self.functions.clone() {
|
if let Some(functions) = self.functions.clone() {
|
||||||
for function in functions {
|
debug!("functions: {:?}", functions.iter().map(|f| format!("{},", f.0)).collect::<String>());
|
||||||
match *function {
|
debug!("{}: {}", &function_name, functions.contains_key(&function_name));
|
||||||
Node::Function { name, body, args } => {
|
if functions.contains_key(&function_name) {
|
||||||
if name == function_name {
|
if let Node::Function { body, .. } = &*(functions[&function_name]) {
|
||||||
for program in body {
|
for program in body {
|
||||||
if let Ok(Some(res)) = self.evaluate(program) {
|
let block = {
|
||||||
|
let blocks = self.blocks.clone();
|
||||||
|
blocks.front().unwrap().clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.blocks.push_front(Block {
|
||||||
|
accept: block.accept.clone(),
|
||||||
|
reject: block.reject.clone(),
|
||||||
|
variables: HashMap::new(),
|
||||||
|
is_split: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let res = self.evaluate(Box::new(*program.clone()));
|
||||||
|
|
||||||
|
if let Ok(Some(res)) = res {
|
||||||
match res {
|
match res {
|
||||||
Variable::Return { value } => {
|
Variable::Return { value } => {
|
||||||
return Ok(Some(*value));
|
return Ok(Some(*value));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
} else if let Err(err) = res {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.blocks.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("Searching external: {}, ({:?})", &function_name, args_value);
|
||||||
|
|
||||||
for func in f {
|
for func in f {
|
||||||
let res = func(function_name.clone(), args_value.clone());
|
let block = self.blocks.front().unwrap();
|
||||||
|
let res = func(function_name.clone(), args_value.clone(), block.accept.clone(), block.reject.clone());
|
||||||
if res.status == ExternalFuncStatus::SUCCESS {
|
if res.status == ExternalFuncStatus::SUCCESS {
|
||||||
return Ok(res.value);
|
return Ok(res.value);
|
||||||
}
|
}
|
||||||
|
if res.status == ExternalFuncStatus::REJECTED {
|
||||||
|
return Err("External function rejected.".to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(format!("Function not found: {}", function_name))
|
Err(format!("Function not found: {}", function_name))
|
||||||
@@ -121,13 +169,15 @@ impl GPSL {
|
|||||||
}
|
}
|
||||||
Node::Operator { kind, lhs, rhs } => {
|
Node::Operator { kind, lhs, rhs } => {
|
||||||
if kind == NodeKind::ASSIGN {
|
if kind == NodeKind::ASSIGN {
|
||||||
|
debug!("Assign: {:?}", self.blocks.front());
|
||||||
|
|
||||||
let rhs = self.evaluate(rhs);
|
let rhs = self.evaluate(rhs);
|
||||||
|
|
||||||
if let Ok(Some(rhs)) = rhs {
|
if let Ok(Some(rhs)) = rhs {
|
||||||
match *(lhs.clone()) {
|
match *(lhs.clone()) {
|
||||||
Node::Lvar { value } => {
|
Node::Lvar { value } => {
|
||||||
self.l_vars.get_mut(&value).unwrap().value = rhs;
|
self.get_local_var_mut(&value).unwrap().value = rhs;
|
||||||
self.l_vars.get_mut(&value).unwrap().status.initialized = true
|
self.get_local_var_mut(&value).unwrap().status.initialized = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -276,7 +326,7 @@ impl GPSL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node::Lvar { value } => {
|
Node::Lvar { value } => {
|
||||||
return Ok(Some(self.l_vars.get(&value).unwrap().value.clone()));
|
return Ok(Some(self.get_local_var(&value).unwrap().value.clone()));
|
||||||
}
|
}
|
||||||
Node::Return { lhs } => {
|
Node::Return { lhs } => {
|
||||||
if let Ok(Some(lhs)) = self.evaluate(lhs) {
|
if let Ok(Some(lhs)) = self.evaluate(lhs) {
|
||||||
@@ -299,7 +349,7 @@ impl GPSL {
|
|||||||
} {
|
} {
|
||||||
if let Ok(Some(res)) = self.evaluate(stmt) {
|
if let Ok(Some(res)) = self.evaluate(stmt) {
|
||||||
match res.clone() {
|
match res.clone() {
|
||||||
Variable::Return { value } => {
|
Variable::Return { .. } => {
|
||||||
return Ok(Some(res));
|
return Ok(Some(res));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -310,7 +360,7 @@ impl GPSL {
|
|||||||
Some(else_stmt) => {
|
Some(else_stmt) => {
|
||||||
if let Ok(Some(res)) = self.evaluate(else_stmt) {
|
if let Ok(Some(res)) = self.evaluate(else_stmt) {
|
||||||
match res.clone() {
|
match res.clone() {
|
||||||
Variable::Return { value } => {
|
Variable::Return { .. } => {
|
||||||
return Ok(Some(res));
|
return Ok(Some(res));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -408,18 +458,36 @@ impl GPSL {
|
|||||||
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
Node::Block { stmts } => {
|
Node::Block { stmts, permission } => {
|
||||||
|
let accept = self.blocks.front().unwrap().accept.clone();
|
||||||
|
let reject = self.blocks.front().unwrap().reject.clone();
|
||||||
|
let (accept, reject) = if let Node::Permission { accept, reject } = *permission.unwrap_or(Box::new(Node::None)) {
|
||||||
|
(accept.iter().map(|p| Permission::from_string(p)).collect(), reject.iter().map(|p| Permission::from_string(p)).collect())
|
||||||
|
} else {
|
||||||
|
(accept, reject)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.blocks.push_front(Block {
|
||||||
|
accept: accept,
|
||||||
|
reject: reject,
|
||||||
|
variables: HashMap::new(),
|
||||||
|
is_split: false
|
||||||
|
});
|
||||||
|
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
let ret = self.evaluate(stmt)?;
|
let ret = self.evaluate(stmt)?;
|
||||||
if let Some(ret) = ret {
|
if let Some(ret) = ret {
|
||||||
match ret.clone() {
|
match ret.clone() {
|
||||||
Variable::Return { value } => {
|
Variable::Return { .. } => {
|
||||||
return Ok(Some(ret));
|
return Ok(Some(ret));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.blocks.pop_front();
|
||||||
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
Node::Define { name, var_type } => {
|
Node::Define { name, var_type } => {
|
||||||
@@ -434,7 +502,7 @@ impl GPSL {
|
|||||||
} else {
|
} else {
|
||||||
return Err(format!("{}: 未知の型です。", var_type));
|
return Err(format!("{}: 未知の型です。", var_type));
|
||||||
};
|
};
|
||||||
self.l_vars.insert(
|
self.blocks.front_mut().unwrap().variables.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
LocalVariable {
|
LocalVariable {
|
||||||
name,
|
name,
|
||||||
@@ -442,36 +510,40 @@ impl GPSL {
|
|||||||
status: VariableStatus::default(),
|
status: VariableStatus::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
debug!("Define: {:?}", self.blocks.front());
|
||||||
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
_ => { Ok(None) },
|
_ => { Ok(None) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, function_name: String, function_args: Vec<Box<Node>>) -> Result<Variable, String> {
|
pub fn run(&mut self, function_name: String, _: Vec<Box<Node>>) -> Result<Variable, String> {
|
||||||
|
debug!("functions: {:?}", self.functions);
|
||||||
debug!("searching {}", function_name);
|
debug!("searching {}", function_name);
|
||||||
|
self.blocks.push_front(Block {
|
||||||
|
accept: vec![Permission::Administrator, Permission::StdIo],
|
||||||
|
reject: vec![],
|
||||||
|
variables: HashMap::new(),
|
||||||
|
is_split: true
|
||||||
|
});
|
||||||
if let Some(functions) = self.functions.clone() {
|
if let Some(functions) = self.functions.clone() {
|
||||||
for function in functions {
|
if let Node::Function { body, .. } = &*(functions[&function_name]) {
|
||||||
match *function {
|
|
||||||
Node::Function { name, body, args } => {
|
|
||||||
if name == function_name {
|
|
||||||
debug!("running: {}", function_name);
|
|
||||||
for program in body {
|
for program in body {
|
||||||
if let Ok(Some(res)) = self.evaluate(program) {
|
let res = self.evaluate(Box::new(*program.clone()));
|
||||||
|
if let Ok(Some(res)) = res {
|
||||||
match res {
|
match res {
|
||||||
Variable::Return { value } => {
|
Variable::Return { value } => {
|
||||||
return Ok(*value);
|
return Ok(*value);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
} else if let Err(err) = res {
|
||||||
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Variable::None {})
|
Ok(Variable::None {})
|
||||||
1
src/vm/mod.rs
Normal file
1
src/vm/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod gpsl;
|
||||||
17
test.gpsl
17
test.gpsl
@@ -1,5 +1,14 @@
|
|||||||
fn main() {
|
|
||||||
let a: String;
|
fn untrusted_function(a: num) $(accept[StdIo]) {
|
||||||
a = "test";
|
println("test");
|
||||||
println(a);
|
}
|
||||||
|
|
||||||
|
fn main() $(accept[Administrator, StdIo]) {
|
||||||
|
println("1");
|
||||||
|
|
||||||
|
$(accept[StdIo], reject[Administrator]) {
|
||||||
|
untrusted_function();
|
||||||
|
}
|
||||||
|
|
||||||
|
println("2");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user