Skip to content

Commit 82d1e42

Browse files
committed
feat: add missing compiler options to boreal-py
1 parent b8f980d commit 82d1e42

File tree

3 files changed

+85
-10
lines changed

3 files changed

+85
-10
lines changed

boreal-cli/tests/cli.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,18 +1163,23 @@ rule my_rule {
11631163
let path = input.path().display();
11641164

11651165
// Test match data only
1166-
test_scan(&["-s", "--match-max-length=5"], &[rule_file.path()], input.path(), |cmd| {
1167-
cmd.assert()
1168-
.stdout(format!(
1169-
r#"my_rule {path}
1166+
test_scan(
1167+
&["-s", "--match-max-length=5"],
1168+
&[rule_file.path()],
1169+
input.path(),
1170+
|cmd| {
1171+
cmd.assert()
1172+
.stdout(format!(
1173+
r#"my_rule {path}
11701174
0x0:$a: <1234
11711175
0xb:$a: <1234
11721176
0x14:$a: <1>
11731177
"#
1174-
))
1175-
.stderr("")
1176-
.success();
1177-
});
1178+
))
1179+
.stderr("")
1180+
.success();
1181+
},
1182+
);
11781183
}
11791184

11801185
#[test]

boreal-py/src/lib.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,16 @@ fn boreal(m: &Bound<'_, PyModule>) -> PyResult<()> {
134134
/// otherwise.
135135
/// profile: Profile to use when compiling the rules. If not specified,
136136
/// `CompilerProfile::Speed` is used.
137-
/// max_strings_per_rule: Maximum number of strings allowed in a single rule.
138-
/// If a rule has more strings than this limit, its compilation will fail.
137+
/// max_strings_per_rule: Maximum number of strings allowed in a single rule.
138+
/// If a rule has more strings than this limit, its compilation will fail.
139+
/// max_condition_depth: Maximum depth in a rule's condition AST.
140+
/// Defensive limit used to prevent stack overflow.
141+
/// parse_expr_recursion_limit: Maximum recursion depth allowed when
142+
/// parsing an expression.
143+
/// Defensive limit used to prevent stack overflow.
144+
/// parse_string_recursion_limit: Maximum recursion depth allowed when
145+
/// parsing a regex or a hex-string.
146+
/// Defensive limit used to prevent stack overflow.
139147
///
140148
/// Returns:
141149
/// a `Scanner` object that holds the compiled rules.
@@ -158,6 +166,9 @@ fn boreal(m: &Bound<'_, PyModule>) -> PyResult<()> {
158166
strict_escape=None,
159167
profile=None,
160168
max_strings_per_rule=None,
169+
max_condition_depth=None,
170+
parse_expr_recursion_limit=None,
171+
parse_string_recursion_limit=None,
161172
))]
162173
#[allow(clippy::too_many_arguments)]
163174
fn compile(
@@ -173,6 +184,9 @@ fn compile(
173184
strict_escape: Option<bool>,
174185
profile: Option<&CompilerProfile>,
175186
max_strings_per_rule: Option<usize>,
187+
max_condition_depth: Option<u32>,
188+
parse_expr_recursion_limit: Option<u8>,
189+
parse_string_recursion_limit: Option<u8>,
176190
) -> PyResult<scanner::Scanner> {
177191
let mut compiler = build_compiler(profile);
178192

@@ -192,6 +206,15 @@ fn compile(
192206
if let Some(value) = max_strings_per_rule {
193207
params = params.max_strings_per_rule(value);
194208
}
209+
if let Some(limit) = max_condition_depth {
210+
params = params.max_condition_depth(limit);
211+
}
212+
if let Some(limit) = parse_expr_recursion_limit {
213+
params = params.parse_expression_recursion_limit(limit);
214+
}
215+
if let Some(limit) = parse_string_recursion_limit {
216+
params = params.parse_string_recursion_limit(limit);
217+
}
195218

196219
compiler.set_params(params);
197220

boreal-py/tests/test_compile.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,50 @@ def test_compiler_max_strings_per_rule():
409409

410410
# Parameter is not saved, so without it, the compilation works
411411
boreal.compile(source=source)
412+
413+
414+
def test_compiler_max_condition_depth():
415+
source = """
416+
rule a {
417+
condition:
418+
5 + (4 - (3 + (2 * 1)))
419+
}
420+
"""
421+
422+
with pytest.raises(boreal.SyntaxError):
423+
boreal.compile(source=source, max_condition_depth=2)
424+
425+
# Parameter is not saved, so without it, the compilation works
426+
boreal.compile(source=source)
427+
428+
429+
def test_compiler_parse_expression_recursion_limit():
430+
source = """
431+
rule a {
432+
condition:
433+
5 + (4 - (3 + (2 * 1)))
434+
}
435+
"""
436+
437+
with pytest.raises(boreal.SyntaxError):
438+
boreal.compile(source=source, parse_expression_recursion_limit=2)
439+
440+
# Parameter is not saved, so without it, the compilation works
441+
boreal.compile(source=source)
442+
443+
444+
def test_compiler_parse_string_recursion_limit():
445+
source = """
446+
rule a {
447+
strings:
448+
$ = { A0 (B0 (C0 (D0 (E0 | F0)))) }
449+
condition:
450+
true
451+
}
452+
"""
453+
454+
with pytest.raises(boreal.SyntaxError):
455+
boreal.compile(source=source, parse_string_recursion_limit=2)
456+
457+
# Parameter is not saved, so without it, the compilation works
458+
boreal.compile(source=source)

0 commit comments

Comments
 (0)