Skip to content

Commit 99af6ef

Browse files
committed
feat: validate lookbehind in Java
1 parent a72e670 commit 99af6ef

File tree

5 files changed

+48
-14
lines changed

5 files changed

+48
-14
lines changed

pomsky-lib/afl-fuzz/src/main.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
};
88

99
use arbitrary::{Arbitrary, Unstructured};
10-
use pomsky::{options::RegexFlavor, Expr};
10+
use pomsky::{Expr, options::RegexFlavor};
1111
use regex::RegexSet;
1212
use regex_test::{Outcome, RegexTest};
1313

@@ -82,11 +82,11 @@ fn check(
8282
};
8383
if let Outcome::Error(e) = outcome {
8484
let e = e.trim();
85-
if let Some(ignored_errors) = ignored_errors.get(&flavor) {
86-
if ignored_errors.is_match(e) {
87-
debug!(f, " {regex:?} ({flavor:?}) ERROR IGNORED: {e}");
88-
return;
89-
}
85+
if let Some(ignored_errors) = ignored_errors.get(&flavor)
86+
&& ignored_errors.is_match(e)
87+
{
88+
debug!(f, " {regex:?} ({flavor:?}) ERROR IGNORED: {e}");
89+
return;
9090
}
9191

9292
debug!(ef, "\n{expr:?}\n{flavor:?}|{regex:?}|{e}\n");

pomsky-lib/src/diagnose/compile_error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,10 @@ impl core::fmt::Display for CompileErrorKind {
216216
)
217217
}
218218
CompileErrorKind::LookbehindNotConstantLength { flavor } => match flavor {
219-
RegexFlavor::Pcre | RegexFlavor::Python => write!(
219+
RegexFlavor::Pcre | RegexFlavor::Python | RegexFlavor::Java => write!(
220220
f,
221221
"In the {flavor:?} flavor, lookbehinds must have a {} length",
222-
if flavor == &RegexFlavor::Pcre { "bounded" } else { "constant" }
222+
if flavor == &RegexFlavor::Python { "constant" } else { "bounded" }
223223
),
224224
_ => write!(f, "This kind of lookbehind is not supported in the {flavor:?} flavor"),
225225
},

pomsky-lib/src/exprs/lookaround.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ impl RegexLookaround {
6060
RegexFlavor::Pcre => {
6161
content.validate_in_lookbehind_pcre()?;
6262
}
63-
// TODO: Java, see <https://github.com/pomsky-lang/pomsky/issues/69>
63+
RegexFlavor::Java => {
64+
content.validate_in_lookbehind_java()?;
65+
}
6466
_ => {}
6567
}
6668
}

pomsky-lib/src/exprs/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ impl Expr {
9191
Ok(compiled) => compiled,
9292
Err(e) => return (None, vec![e.diagnostic(input)]),
9393
};
94-
if let Some(rec_span) = validator.first_recursion {
95-
if !compiled.terminates() {
96-
let error = CompileErrorKind::InfiniteRecursion.at(rec_span);
97-
return (None, vec![error.diagnostic(input)]);
98-
}
94+
if let Some(rec_span) = validator.first_recursion
95+
&& !compiled.terminates()
96+
{
97+
let error = CompileErrorKind::InfiniteRecursion.at(rec_span);
98+
return (None, vec![error.diagnostic(input)]);
9999
}
100100
let count = compiled.optimize();
101101

pomsky-lib/src/regex/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,38 @@ impl Regex {
149149
}
150150
}
151151

152+
pub(super) fn validate_in_lookbehind_java(&self) -> Result<(), CompileErrorKind> {
153+
match self {
154+
Regex::Group(g) => {
155+
for part in &g.parts {
156+
part.validate_in_lookbehind_java()?;
157+
}
158+
Ok(())
159+
}
160+
Regex::Alternation(alt) => {
161+
for part in &alt.parts {
162+
part.validate_in_lookbehind_java()?;
163+
}
164+
Ok(())
165+
}
166+
Regex::Repetition(r) => match r.kind.upper_bound {
167+
Some(_) => Ok(()),
168+
_ => {
169+
Err(CompileErrorKind::LookbehindNotConstantLength { flavor: RegexFlavor::Java })
170+
}
171+
},
172+
Regex::Grapheme => Err(CompileErrorKind::UnsupportedInLookbehind {
173+
flavor: RegexFlavor::Java,
174+
feature: Feature::Grapheme,
175+
}),
176+
Regex::Reference(_) => Err(CompileErrorKind::UnsupportedInLookbehind {
177+
flavor: RegexFlavor::Java,
178+
feature: Feature::Backreference,
179+
}),
180+
_ => Ok(()),
181+
}
182+
}
183+
152184
pub(super) fn is_single_char(&self) -> bool {
153185
if let Regex::Literal(l) = self {
154186
!l.is_empty() && l.chars().nth(1).is_none()

0 commit comments

Comments
 (0)