Misleading Regex Argument In String Methods

ID

java.string_regex_literal_dot

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

code-style

Description

Reports calls to String.split, String.replaceAll, String.replaceFirst and String.matches whose first argument is one of three values that read as a regular expression but are almost always meant as plain text: the literal ".", the literal "|", or File.separator.

Rationale

The first argument of these four methods is a pattern, not a plain string, and three values are routinely passed as though it were one.

. matches any character, so it eats the whole input:

"a.b.c".split(".")           // returns String[0] — every char is eaten
"abc".replaceAll(".", "X")   // returns "XXX", not "abc"

| is an alternation between two empty branches, so it matches the zero-length string in front of every character:

"north|south".split("|")             // ["n","o","r","t","h","|","s","o","u","t","h"]
"north|south".replaceAll("|", "-")   // "-n-o-r-t-h-|-s-o-u-t-h-"

File.separator carries whatever the running platform uses. Where that is a backslash the value is the regex escape character, so the pattern is malformed and the call throws PatternSyntaxException — on that platform only, which is how it survives testing elsewhere:

path.split(File.separator);          // throws on a backslash platform

The bug usually hides behind the assumption that the argument is the separator character rather than a pattern describing it.

Remediation

Escape the metacharacter, quote a value that was never meant to be a pattern, or call a method that takes plain text — String.replace(CharSequence, CharSequence) never interprets its argument.

// Escape, when a pattern really is wanted
String[] parts = hostname.split("\\.");
String[] legs  = route.split("\\|");

// Quote, when the separator is computed at runtime
String[] steps = path.split(Pattern.quote(File.separator));

// Or sidestep patterns altogether
String cleaned = text.replace(".", "_");

For filesystem paths, iterating the elements of a NIO Path avoids splitting on a separator in the first place.

What is not reported

matches(".") is a legitimate "exactly one character" test, so the dot is only reported for split, replaceAll and replaceFirst. An argument built at runtime — a concatenation, or a nested call such as Pattern.quote(File.separator) — is not reported either, because the value reaching the matcher is no longer the bare metacharacter.

© 2026 Xygeni. All rights reserved