Java: Add initial version of string replaceAll with no regex query

This commit is contained in:
Owen Mansel-Chan
2025-03-21 16:28:20 +00:00
parent d2a4f1e17a
commit 041adcd63a
5 changed files with 57 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# J-STR-001: Use of `String.replaceAll` with a first argument of a non regular expression
Using `String.replaceAll` is less performant than `String.replace` when the first argument is not a regular expression.
## Overview
The underlying implementation of `String.replaceAll` uses `Pattern.compile` and expects a regular expression as its first argument. However in cases where the argument could be represented by just a plain `String` that does not represent an interesting regular expression, a call to `String.replace` may be more performant as it does not need to compile the regular expression.
## Recommendation
Use `String.replace` instead where a `replaceAll` call uses a trivial string as its first argument.
## Example
```java
public class Test {
void f() {
String s1 = "test";
s1 = s1.replaceAll("t", "x"); // NON_COMPLIANT
s1 = s1.replaceAll(".*", "x"); // COMPLIANT
}
}
```
## References
- [String.replaceAll](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/lang/String.html#replaceAll(java.lang.String,java.lang.String))

View File

@@ -0,0 +1,20 @@
/**
* @id java/string-replace-all-with-non-regex
* @name J-STR-001: Use of `String#replaceAll` with a first argument of a non regular expression
* @description Using `String#replaceAll` is less performant than `String#replace` when the first
* argument is not a regular expression.
* @kind problem
* @precision very-high
* @problem.severity recommendation
* @tags performance
*/
import java
from MethodCall replaceAllCall
where
replaceAllCall.getMethod().hasQualifiedName("java.lang", "String", "replaceAll") and
//only contains characters that could be a simple string
replaceAllCall.getArgument(0).(StringLiteral).getValue().regexpMatch("^[a-zA-Z0-9]+$")
select replaceAllCall,
"Call to 'replaceAll' uses an argument comprised of plain string characters only."

View File

@@ -0,0 +1 @@
| Test.java:4:14:4:36 | replaceAll(...) | Call to 'replaceAll' uses an argument comprised of plain string characters only. |

View File

@@ -0,0 +1 @@
Performance/StringReplaceAllWithNonRegex.ql

View File

@@ -0,0 +1,7 @@
public class Test {
void f() {
String s1 = "test";
s1 = s1.replaceAll("t", "x"); // NON_COMPLIANT
s1 = s1.replaceAll(".*", "x"); // COMPLIANT
}
}