mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Java: Add initial version of string replaceAll with no regex query
This commit is contained in:
28
java/ql/src/Performance/StringReplaceAllWithNonRegex.md
Normal file
28
java/ql/src/Performance/StringReplaceAllWithNonRegex.md
Normal 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))
|
||||
20
java/ql/src/Performance/StringReplaceAllWithNonRegex.ql
Normal file
20
java/ql/src/Performance/StringReplaceAllWithNonRegex.ql
Normal 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."
|
||||
@@ -0,0 +1 @@
|
||||
| Test.java:4:14:4:36 | replaceAll(...) | Call to 'replaceAll' uses an argument comprised of plain string characters only. |
|
||||
@@ -0,0 +1 @@
|
||||
Performance/StringReplaceAllWithNonRegex.ql
|
||||
@@ -0,0 +1,7 @@
|
||||
public class Test {
|
||||
void f() {
|
||||
String s1 = "test";
|
||||
s1 = s1.replaceAll("t", "x"); // NON_COMPLIANT
|
||||
s1 = s1.replaceAll(".*", "x"); // COMPLIANT
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user