diff --git a/compiler/llvm_backend/src/jit.rs b/compiler/llvm_backend/src/jit.rs index 9005daa3..e05cbfe8 100644 --- a/compiler/llvm_backend/src/jit.rs +++ b/compiler/llvm_backend/src/jit.rs @@ -5,8 +5,8 @@ #![cfg(feature = "llvm")] use llvm_sys::core::*; -use llvm_sys::orc2::*; use llvm_sys::orc2::lljit::*; +use llvm_sys::orc2::*; use std::collections::HashMap; use std::ffi::CString; use std::ptr; @@ -60,7 +60,7 @@ impl LLVMJitEngine { // 3. Set host target triple let _host_triple = LLVMOrcLLJITGetExecutionSession(self.jit); // session triple fallback - // We can just keep the default LLVM target triple + // We can just keep the default LLVM target triple // 4. Wrap Module in ThreadSafeModule let tsm = LLVMOrcCreateNewThreadSafeModule(ctx.module, self.ts_ctx); diff --git a/stdlib/src/json.rs b/stdlib/src/json.rs index 8a5a51ca..99f9135a 100644 --- a/stdlib/src/json.rs +++ b/stdlib/src/json.rs @@ -39,7 +39,7 @@ impl StdlibRegistry { None, ) })?; - Ok(parse_json_value(v)) + parse_json_value(v, 0) }, }), ); @@ -92,36 +92,47 @@ pub fn stringify_value(val: &RuntimeValue) -> Result { } } -pub fn parse_json_value(v: serde_json::Value) -> RuntimeValue { +pub fn parse_json_value(v: serde_json::Value, depth: usize) -> Result { + if depth > 128 { + return Err(RuntimeError::new( + RuntimeErrorKind::InvalidOperation("JSON depth limit exceeded".to_string()), + None, + None, + )); + } + match v { - serde_json::Value::Null => RuntimeValue::Null, - serde_json::Value::Bool(b) => RuntimeValue::Bool(b), + serde_json::Value::Null => Ok(RuntimeValue::Null), + serde_json::Value::Bool(b) => Ok(RuntimeValue::Bool(b)), serde_json::Value::Number(num) => { if let Some(i) = num.as_i64() { - RuntimeValue::Int(i) + Ok(RuntimeValue::Int(i)) } else if let Some(f) = num.as_f64() { - RuntimeValue::Float(f) + Ok(RuntimeValue::Float(f)) } else { - RuntimeValue::Null + Ok(RuntimeValue::Null) } } - serde_json::Value::String(s) => RuntimeValue::Str(s), + serde_json::Value::String(s) => Ok(RuntimeValue::Str(s)), serde_json::Value::Array(arr) => { - let items = arr.into_iter().map(parse_json_value).collect::>(); - RuntimeValue::List { + let mut items = Vec::new(); + for item in arr { + items.push(parse_json_value(item, depth + 1)?); + } + Ok(RuntimeValue::List { items: Rc::new(RefCell::new(items)), is_const: false, - } + }) } serde_json::Value::Object(obj) => { let mut entries = IndexMap::new(); for (k, v) in obj { - entries.insert(k, parse_json_value(v)); + entries.insert(k, parse_json_value(v, depth + 1)?); } - RuntimeValue::Map { + Ok(RuntimeValue::Map { entries: Rc::new(RefCell::new(entries)), is_const: false, - } + }) } } } diff --git a/stdlib/tests/stdlib_tests.rs b/stdlib/tests/stdlib_tests.rs index 7d530343..fb243ac9 100644 --- a/stdlib/tests/stdlib_tests.rs +++ b/stdlib/tests/stdlib_tests.rs @@ -186,6 +186,25 @@ fn test_json_module() { } else { panic!("JSON parse result was not a Map"); } + + // Test depth limit + let mut nested_json_str = String::new(); + for _ in 0..200 { + nested_json_str.push_str("{\"nested\":"); + } + nested_json_str.push_str("null"); + for _ in 0..200 { + nested_json_str.push('}'); + } + + let result = parse.call(&mut ctx, vec![RuntimeValue::Str(nested_json_str)]); + assert!(result.is_err()); + if let Err(e) = result { + assert!( + e.message.contains("JSON depth limit exceeded") + || e.message.contains("JSON parse error") + ); + } } #[test]