Skip to content

Commit

Permalink
implemented safe mode
Browse files Browse the repository at this point in the history
  • Loading branch information
lexa-diky committed Jul 10, 2024
1 parent 88efd81 commit 092c446
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 9 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ cargo install hexo

Use `hexo -h` to get complete CLI manual.

### Arguments

- `log-level`
: Set log level, possible values: `debug`, `info`, `warn`, `error`, `none`. Default: `info`.

- `safe`
: Enable safe mode, will disable unsafe functions like `cmd` and `eval`. Default: `false`

### Commands

#### build
Expand All @@ -37,7 +45,6 @@ Takes `source` file in hexo format and compiles it to binary file `output`. Will
hexo watch --source <path to source> --output <path to output>
```


## Syntax

### Emitter
Expand Down Expand Up @@ -142,4 +149,6 @@ Not currently, but this is planned for future releases.
### Isn't `cmd` function highly unsafe?

Yes, safety is no goal of Hexo, please don't run untrusted code with it.
Safe mode might be implemented in the future is there is enough demand for it.

You can use safe mode to disable `cmd` and `eval` functions.
Please add `--safe` flag before command to enable it.
4 changes: 4 additions & 0 deletions src/compiler/compiler_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ impl HexoCompilerContext {
safe_mode
}
}

pub(crate) fn safe_mode(&self) -> bool {
self.safe_mode
}
}
2 changes: 1 addition & 1 deletion src/compiler/hexo_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl HexoCompiler {
source: &TSource,
) -> Result<HexoFile, Error> {
let cst = self.compile_cst(source)?;
let rst_compiler = RstCompiler::new(self);
let rst_compiler = RstCompiler::new(self, self.context.safe_mode());

rst_compiler.compile(&cst).map_err(Error::Rst)
}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/native_fn/implementations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub(crate) fn create_pad_right_native_function() -> NativeFunction {

pub(crate) fn create_cmd_native_function() -> NativeFunction {
NativeFunction::new(
NativeFunctionSignature::new("cmd"),
NativeFunctionSignature::new_unsafe("cmd"),
|arguments, _| {
let command = get_argument_at(&arguments, 0, "cmd")?
.to_string()
Expand Down Expand Up @@ -116,7 +116,7 @@ pub(crate) fn create_pad_native_function() -> NativeFunction {

pub(crate) fn create_eval_native_function() -> NativeFunction {
NativeFunction::new(
NativeFunctionSignature::new("eval"),
NativeFunctionSignature::new_unsafe("eval"),
|arguments, compiler| {
let buffer = get_argument_at(&arguments, 0, "eval")?.clone();
let source = LiteralCompilerSource::anonymous(
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/native_fn/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ pub(crate) struct NativeFunctionIndex {
}

impl NativeFunctionIndex {

pub(crate) fn new() -> NativeFunctionIndex {
NativeFunctionIndex {
functions: Self::create_native_functions(),
}
}

pub(crate) fn find(&self, name: String) -> Option<&NativeFunction> {
return self.functions.iter().find(|f| f.signature().name == name);
return self.functions.iter().find(|f| f.signature().name() == name);
}

fn create_native_functions() -> Vec<NativeFunction> {
Expand Down
19 changes: 18 additions & 1 deletion src/compiler/native_fn/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,32 @@ use crate::compiler::HexoCompiler;

#[derive(Clone, Debug)]
pub(crate) struct NativeFunctionSignature {
pub(crate) name: String,
name: String,
is_safe: bool
}

impl NativeFunctionSignature {
pub(crate) fn new(name: &str) -> NativeFunctionSignature {
NativeFunctionSignature {
name: String::from(name),
is_safe: true
}
}

pub(crate) fn new_unsafe(name: &str) -> NativeFunctionSignature {
NativeFunctionSignature {
name: String::from(name),
is_safe: false
}
}

pub(crate) fn name(&self) -> &str {
&self.name
}

pub(crate) fn is_safe(&self) -> bool {
self.is_safe
}
}

type NativeFunctionExecutor = fn(&HashMap<String, ByteBuffer>, &HexoCompiler) -> Result<ByteBuffer, Error>;
Expand Down
13 changes: 11 additions & 2 deletions src/compiler/rst/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ use crate::util::id::HexoId;

pub(crate) struct RstCompiler<'a> {
parent: &'a HexoCompiler,
safe_mode: bool,
}

impl RstCompiler<'_> {
pub(crate) fn new(parent: &HexoCompiler) -> RstCompiler {
RstCompiler { parent }
pub(crate) fn new(parent: &HexoCompiler, safe_mode: bool) -> RstCompiler {
RstCompiler { parent, safe_mode }
}

pub(crate) fn compile(&self, cst: &CstFile) -> Result<HexoFile, Error> {
Expand Down Expand Up @@ -83,6 +84,14 @@ impl RstCompiler<'_> {
) -> Result<(), Error> {
let native_function = context.get_native_function(function_name.as_str());
if let Some(native_function) = native_function {
if self.safe_mode && !native_function.signature().is_safe() {
return Err(
Error::NativeFunctionIsUnsafe {
name: native_function.signature().name().to_string()
}
)
}

let executor = native_function.executor();
let mut params_buffer = HashMap::new();

Expand Down
4 changes: 4 additions & 0 deletions src/compiler/rst/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub(crate) enum Error {
UnresolvedConstant { name: String },
UnresolvedFunction { name: String },
NativeFunctionExecution(crate::compiler::native_fn::Error),
NativeFunctionIsUnsafe { name: String },
}

impl std::fmt::Display for Error {
Expand All @@ -17,6 +18,9 @@ impl std::fmt::Display for Error {
Error::NativeFunctionExecution(e) => {
write!(f, "Native function execution error: {}", e)
}
Error::NativeFunctionIsUnsafe { name } => {
write!(f, "Native function is unsafe: {}", name)
}
}
}
}
Expand Down

0 comments on commit 092c446

Please sign in to comment.