Rename RegexMatch and only include expressions

This commit is contained in:
Owen Mansel-Chan
2026-02-13 22:45:23 +00:00
parent 953ff9f0d0
commit 1fefa989d7
6 changed files with 21 additions and 61 deletions

View File

@@ -7,71 +7,35 @@ overlay[local?]
module;
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.frameworks.JavaxAnnotations
/**
* A data-flow node that executes a regular expression.
* An expression that represents a regular expression match.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexExecution::Range` instead.
* extend `RegexMatch::Range` instead.
*/
class RegexExecution extends DataFlow::Node instanceof RegexExecution::Range {
/** Gets the data flow node for the regex being executed by this node. */
DataFlow::Node getRegex() { result = super.getRegex() }
class RegexMatch extends Expr instanceof RegexMatch::Range {
/** Gets the expression for the regex being executed by this node. */
Expr getRegex() { result = super.getRegex() }
/** Gets a data flow node for the string to be searched or matched against. */
DataFlow::Node getString() { result = super.getString() }
/** Gets an expression for the string to be searched or matched against. */
Expr getString() { result = super.getString() }
/**
* Gets the name of this regex execution, typically the name of an executing method.
* Gets the name of this regex match, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
string getName() { result = super.getName() }
}
/** Provides classes for modeling new regular-expression execution APIs. */
module RegexExecution {
/**
* A data flow node that executes a regular expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexExecution` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the data flow node for the regex being executed by this node. */
abstract DataFlow::Node getRegex();
/** Gets a data flow node for the string to be searched or matched against. */
abstract DataFlow::Node getString();
/**
* Gets the name of this regex execution, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
abstract string getName();
}
private class RangeFromExpr extends Range {
private RegexExecutionExpr::Range ree;
RangeFromExpr() { this.asExpr() = ree }
override DataFlow::Node getRegex() { result.asExpr() = ree.getRegex() }
override DataFlow::Node getString() { result.asExpr() = ree.getString() }
override string getName() { result = ree.getName() }
}
}
/** Provides classes for modeling new regular-expression execution APIs. */
module RegexExecutionExpr {
/** Provides classes for modeling regular-expression execution APIs. */
module RegexMatch {
/**
* An expression that executes a regular expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexExecution` instead.
* extend `RegexMatch` instead.
*/
abstract class Range extends Expr {
/** Gets the expression for the regex being executed by this node. */
@@ -81,7 +45,7 @@ module RegexExecutionExpr {
abstract Expr getString();
/**
* Gets the name of this regex execution, typically the name of an executing method.
* Gets the name of this regex match, typically the name of an executing method.
* This is used for nice alert messages and should include the module if possible.
*/
abstract string getName();

View File

@@ -48,7 +48,7 @@ class StringContainsMethod extends Method {
}
/** A call to the `java.lang.String.matches` method. */
class StringMatchesCall extends MethodCall, RegexExecutionExpr::Range {
class StringMatchesCall extends MethodCall, RegexMatch::Range {
StringMatchesCall() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypeString and

View File

@@ -171,7 +171,7 @@ class WebServiceRefAnnotation extends Annotation {
/**
* A `@javax.validation.constraints.Pattern` annotation.
*/
class PatternAnnotation extends Annotation, RegexExecutionExpr::Range {
class PatternAnnotation extends Annotation, RegexMatch::Range {
PatternAnnotation() {
this.getType()
.hasQualifiedName(["javax.validation.constraints", "jakarta.validation.constraints"],

View File

@@ -82,7 +82,7 @@ class PatternMatcherCall extends MethodCall {
}
/** A call to the `matches` method of `java.util.regex.Pattern`. */
class PatternMatchesCall extends MethodCall, RegexExecutionExpr::Range {
class PatternMatchesCall extends MethodCall, RegexMatch::Range {
PatternMatchesCall() { this.getMethod() instanceof PatternMatchesMethod }
override Expr getRegex() { result = this.getArgument(0) }
@@ -93,7 +93,7 @@ class PatternMatchesCall extends MethodCall, RegexExecutionExpr::Range {
}
/** A call to the `matches` method of `java.util.regex.Matcher`. */
class MatcherMatchesCall extends MethodCall, RegexExecutionExpr::Range {
class MatcherMatchesCall extends MethodCall, RegexMatch::Range {
MatcherMatchesCall() { this.getMethod() instanceof MatcherMatchesMethod }
/**

View File

@@ -431,9 +431,7 @@ private class ReplaceDirectoryCharactersSanitizer extends StringReplaceOrReplace
* Holds if `matchesCall` confirms that `checkedExpr` does not contain any directory characters
* on the given `branch`.
*/
private predicate isMatchesCall(
RegexExecutionExpr::Range regexMatch, Expr checkedExpr, boolean branch
) {
private predicate isMatchesCall(RegexMatch regexMatch, Expr checkedExpr, boolean branch) {
exists(CompileTimeConstantExpr target, string targetValue |
target = regexMatch.getRegex() and
target.getStringValue() = targetValue and

View File

@@ -41,9 +41,9 @@ class SimpleTypeSanitizer extends DataFlow::Node {
* make the type recursive. Otherwise use `RegexpCheckBarrier`.
*/
predicate regexpMatchGuardChecks(Guard guard, Expr e, boolean branch) {
exists(RegexExecutionExpr::Range ree | not ree instanceof Annotation |
guard = ree and
e = ree.getString()
exists(RegexMatch rm | not rm instanceof Annotation |
guard = rm and
e = rm.getString()
) and
branch = true
}
@@ -60,8 +60,6 @@ class RegexpCheckBarrier extends DataFlow::Node {
// Annotations don't fit into the model of barrier guards because the
// annotation doesn't dominate the sanitized expression, so we instead
// treat them as barriers directly.
exists(RegexExecutionExpr::Range ree | ree instanceof Annotation |
this.asExpr() = ree.getString()
)
exists(RegexMatch rm | rm instanceof Annotation | this.asExpr() = rm.getString())
}
}