In the past quarter, we have improved our Java Analyzer significantly. In this release, you’ll see a sturdier Java analyzer, coverage for new issues, and various false-positive fixes. Scroll down for all the details.
Faster, more reliable analysis
We have a new back-end for the Java Analyzer now, which is faster and more reliable than ever. With this, we have managed to improve the speed of Java analyses by over 2.5 times. Java analysis timeouts are also a thing of the past now.
How did we do this?
In its beta days, the Java Analyzer used to build your projects and run bytecode analysis on the compilation results. This worked out about as well as anyone could have expected it to, and used to time out in many cases if your project took too long to compile.
We now directly analyze Java code by creating an Abstract Syntax Tree (AST) for each file, inspecting the AST, and extracting information regarding classes, variables, and methods. This is essentially the beginning of what javac
does. Since we don’t need to worry about generating bytecode, we can be even more fault-tolerant during analysis as well. The new Java Analyzer is very difficult to crash, (It even shrugged off an OutOfMemoryException
once while testing it) and is much faster than the older runtime, which we are calling the “legacy” runtime now.
Legacy mode
Since we are in the process of migrating all the issues previously detected by the analyzer to the new runtime, you might notice that some issues are not being raised anymore. To remedy this, we have introduced legacy
mode, which enables old Java Analyzer beta features. This mode will likely turn up more issues but may result in slower analysis with a higher chance of timeouts occurring. We are actively working on migrating all the issues to the new runtime.
You can enable legacy mode on your repo by modifying the Java
section of your .deepsource.toml
file to add the legacy
flag:
version = 1
[[analyzers]]
name = "java"
enabled = true
[analyzers.meta]
runtime_version = 11
legacy = true
Note: We highly recommend not using Legacy mode to have a better experience. Legacy mode will be deprecated once we finish migrating all issues. Usage of this flag in your config will be ignored upon deprecation.
Other additions and improvements
New issues
We’ve brought in a number of new issues, including an assortment of security issues; here’s a sampler:
JAVA-E0394: Regex strings must be valid
This issue will trigger if Pattern.compile()
and other related methods are called with an invalid regex string.
Pattern regex = Pattern.compile("(////)"); // This is an invalid regex in Java.
JAVA-S1004: CBC and ECB modes are insecure
CBC (Cipher Block Chaining) is a mode of block-based encryption which uses previously encrypted blocks as input when encrypting the next plain-text block. CBC encryption is flawed due to its vulnerability to the Padding Oracle Attack.
ECB is an encryption mode that is even more broken and renders data encrypted with it exposed to a number of cryptographic attacks.
This issue will be raised if usage of CBC or ECB mode is detected.
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Susceptible to padding oracle attacks.
Cipher d = Cipher.getInstance("AES"); // The default mode if no mode is specified is ECB.
JAVA-S1009: Instances of XMLStreamReader
should be secure
Instances of the XMLStreamReader
class are created through the XMLInputFactory
API, which also allows one to set input processing options for any created XMLStreamReader
s. If the correct flags are not set, and untrusted data is treated as an XML stream, it is possible that a security breach could occur via specially crafted XML payloads. When using XMLInputFactory
, the IS_SUPPORTING_EXTERNAL_ENTITIES
and/or SUPPORT_DTD
flags must be set to false
to prevent side-channel attacks.
This issue will be raised if the analyzer detects that any of these flags are not set to false
.
InputStream input = ...;
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLStreamReader reader = factory.createXMLStreamReader(input); // we have set no flags here.
False-positive fixes
We’ve resolved false positives for the following issues:
JAVA-W0324: Private method is never called
This issue was earlier mistakenly reported if a private method was used in a nested class. This is no longer the case, and private methods defined within a class and used within nested classes will not be reported as unused.
class WithNested {
private void method() { ... } // This method will not be reported.
class Nested {
void method2() {
WithNested.this.method();
}
}
}
Also, this issue will no longer be reported on methods marked with JUnit test annotations such as @Test
and @BeforeEach
. Annotations from dependency injection frameworks like @Inject
and @Autowired
as well as annotations from the Spring JPA library, such as @PreUpdate
are also supported.
@Autowired
public void someComponentMethod(...) { ...}
Another case where this issue was mistakenly reported for private methods that were used as method references is also fixed:
public class PrivateMethodReference {
public void method() {
Lists.of(1, 2, 3, 4, 5)
.stream()
.map(this::privateMethod) // the privateMethod method will correctly be recognised as being used now.
.forEach(System.out::println);
}
private String privateMethod(int val) {
return "number " + val;
}
}
Additionally, several edge cases present during the detection of this issue have been fixed.
JAVA-W0100: equals
was not overridden from superclass
This issue will no longer falsely report enumerations since they are not supposed to explicitly implement equals
.
JAVA-W0280: ==
should not be used to compare objects
This issue was wrongly reported within equals
methods, even ones auto-generated by IDEs such as IntelliJ IDEA which may be well in their rights to perform reference comparisons. DeepSource will no longer report such valid usages.
JAVA-P0062: Inefficient use of String
constructor
This issue was incorrectly raised for any usage of the String()
constructor, rather than only for strings constructed from string literals (new String("abc")
for example).
That’s all for now, but keep checking back; we’re working on even more cool things!