Skip to content

Commit

Permalink
Restricted pragma directives to only allow basic constructs for now
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacShelton committed Aug 28, 2024
1 parent d399d3d commit cc2fc3f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub struct BuildOptions {
pub interpret: bool,
pub coerce_main_signature: bool,
pub excute_result: bool,
pub allow_experimental_pragma_features: bool,
pub use_pic: Option<bool>,
pub target: Target,
pub infrastructure: Option<PathBuf>,
Expand All @@ -133,6 +134,7 @@ impl Default for BuildOptions {
interpret: false,
coerce_main_signature: true,
excute_result: false,
allow_experimental_pragma_features: false,
use_pic: None,
target: Target::HOST,
infrastructure: Some(infrastructure),
Expand Down
69 changes: 63 additions & 6 deletions src/pragma_section/parse.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use super::PragmaSection;
use crate::{
ast::{AstFile, Function, Parameters, StmtKind, TypeKind},
ast::{AstFile, Expr, ExprKind, Function, Parameters, Stmt, StmtKind, TypeKind},
diagnostics::ErrorDiagnostic,
inflow::Inflow,
parser::{self, error::ParseError, Input},
show::{into_show, Show},
source_files::Source,
token::{Token, TokenKind},
};

impl PragmaSection {
pub fn parse<'a, I: Inflow<Token>>(
allow_experimental_pragma_features: bool,
mut input: Input<'a, I>,
) -> Result<(PragmaSection, Input<'a, I>), Box<dyn Show>> {
// pragma ...
Expand All @@ -33,11 +36,18 @@ impl PragmaSection {
// "Whole-file" mode

// Parse top-level contructs until we hit a '}'
while !parser.input.peek_is(TokenKind::CloseCurly) {
parser
.parse_top_level(&mut ast_file, vec![])
.map_err(into_show)?;
parser.input.ignore_newlines();
if allow_experimental_pragma_features {
while !parser.input.peek_is_or_eof(TokenKind::CloseCurly) {
parser
.parse_top_level(&mut ast_file, vec![])
.map_err(into_show)?;
parser.input.ignore_newlines();
}
} else {
return Err(Box::new(ErrorDiagnostic::new(
"Whole-file pragma directives are an experimental feature and may be removed",
pragma_source,
)));
}

// Eat the final '}'
Expand All @@ -62,6 +72,12 @@ impl PragmaSection {
vec![StmtKind::Expr(expr).at(expr_source)]
};

if !allow_experimental_pragma_features {
for stmt in stmts.iter() {
restrict_allowed_stmt(stmt)?;
}
}

ast_file.functions.push(Function {
name: "main".into(),
parameters: Parameters {
Expand Down Expand Up @@ -92,3 +108,44 @@ impl PragmaSection {
))
}
}

fn restrict_allowed_stmt(stmt: &Stmt) -> Result<(), Box<dyn Show>> {
match &stmt.kind {
StmtKind::Expr(inner) => restrict_allowed_expr(inner)?,
_ => return Err(found_forbidden_stmt(stmt.source)),
}

Ok(())
}

fn restrict_allowed_expr(expr: &Expr) -> Result<(), Box<dyn Show>> {
match &expr.kind {
ExprKind::NullTerminatedString(_) => (),
ExprKind::Call(call) => {
if call.expected_to_return.is_some() {
return Err(found_forbidden_expr(expr.source));
}

for argument in call.arguments.iter() {
restrict_allowed_expr(argument)?;
}
}
_ => return Err(found_forbidden_expr(expr.source)),
}

Ok(())
}

fn found_forbidden_stmt(source: Source) -> Box<dyn Show> {
Box::new(ErrorDiagnostic::new(
"Support for this statement inside pragma directives is an experimental feature that may be removed",
source,
))
}

fn found_forbidden_expr(source: Source) -> Box<dyn Show> {
Box::new(ErrorDiagnostic::new(
"Support for this expression inside pragma directives is an experimental feature that may be removed",
source,
))
}
1 change: 1 addition & 0 deletions src/pragma_section/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl PragmaSection {
coerce_main_signature: false,
excute_result: false,
use_pic: None,
allow_experimental_pragma_features: false,
target: Target::HOST,
infrastructure: None,
},
Expand Down
3 changes: 2 additions & 1 deletion src/workspace/compile/module/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ pub fn compile_module_file<'a>(
let mut settings = None;

while input.peek_is(TokenKind::PragmaKeyword) {
let (section, rest_input) = PragmaSection::parse(input)?;
let (section, rest_input) =
PragmaSection::parse(compiler.options.allow_experimental_pragma_features, input)?;
input = rest_input;
settings = Some(section.run(compiler, path, settings)?);
input.ignore_newlines();
Expand Down

0 comments on commit cc2fc3f

Please sign in to comment.