Skip to content

Commit 991bf5f

Browse files
SONARJAVA-5818: Fix FPs caused by missing state reset in CipherBlockChainingCheck
1 parent 3f2f593 commit 991bf5f

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package checks.security;
2+
3+
import java.security.InvalidAlgorithmParameterException;
4+
import java.security.InvalidKeyException;
5+
import java.security.SecureRandom;
6+
import javax.crypto.Cipher;
7+
import javax.crypto.spec.IvParameterSpec;
8+
import javax.crypto.spec.SecretKeySpec;
9+
10+
import static javax.crypto.Cipher.ENCRYPT_MODE;
11+
12+
// This file contains some trivial cases to check that CipherBlockChainingCheck resets its class/file-level state properly.
13+
// For this purpose, the tests of CipherBlockChainingCheck analyze this file immediately after and before the main test sources.
14+
//
15+
// See the other test sources for proper tests of CipherBlockChainingCheck.
16+
public class CipherBlockChainingCheckShouldResetState {
17+
static Cipher cipher;
18+
static SecretKeySpec secretKey;
19+
20+
void tn_control() throws InvalidAlgorithmParameterException, InvalidKeyException {
21+
final byte[] iv = secureIv();
22+
cipher.init(ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); // Compliant
23+
}
24+
25+
void tp_control() throws InvalidAlgorithmParameterException, InvalidKeyException {
26+
final byte[] iv = insecureIv();
27+
cipher.init(ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); // Noncompliant
28+
}
29+
30+
private byte[] secureIv() {
31+
return new SecureRandom().generateSeed(12);
32+
}
33+
34+
private byte[] insecureIv() {
35+
return new byte[12];
36+
}
37+
}

java-checks/src/main/java/org/sonar/java/checks/security/CipherBlockChainingCheck.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public void visitNode(Tree tree) {
100100
public void leaveNode(Tree tree) {
101101
if (tree == outermostClass) {
102102
ivFactoryFinder.clear();
103+
outermostClass = null;
103104
}
104105
super.leaveNode(tree);
105106
}

java-checks/src/test/java/org/sonar/java/checks/security/CipherBlockChainingCheckTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class CipherBlockChainingCheckTest {
2626
private static final String BASE_PATH = "checks/security";
2727
private static final String DEFAULT_SOURCE_PATH = BASE_PATH + "/CipherBlockChainingCheck.java";
2828
private static final String CUSTOM_IV_FACTORY_DETECTION_SOURCE_PATH = BASE_PATH + "/CipherBlockChainingCheckShouldDetectCustomIVFactories.java";
29+
private static final String STATE_RESET_TEST_FILE_SOURCE_PATH = BASE_PATH + "/CipherBlockChainingCheckShouldResetState.java";
2930

3031
@Test
3132
void test() {
@@ -58,4 +59,28 @@ void should_detect_custom_iv_factories_non_compiling() {
5859
.withCheck(new CipherBlockChainingCheck())
5960
.verifyIssues();
6061
}
62+
63+
@Test
64+
void should_reset_state_between_class_and_file_analyses() {
65+
// CipherBlockChainingCheck needs to properly reset its state in between analyzing classes/files.
66+
// Otherwise, it might not refresh its knowledge about secure factory methods that exist in a given class.
67+
// This test validates the reset, by analyzing another file before and after the main test source file.
68+
69+
// First, lets verify that the additional testing file passes the verifier on its own
70+
CheckVerifier.newVerifier()
71+
.onFile(mainCodeSourcesPath(STATE_RESET_TEST_FILE_SOURCE_PATH))
72+
.withCheck(new CipherBlockChainingCheck())
73+
.verifyIssues();
74+
75+
// Then lets interleave its analysis with the main file from above
76+
CheckVerifier.newVerifier()
77+
.onFiles(mainCodeSourcesPath(STATE_RESET_TEST_FILE_SOURCE_PATH), mainCodeSourcesPath(CUSTOM_IV_FACTORY_DETECTION_SOURCE_PATH))
78+
.withCheck(new CipherBlockChainingCheck())
79+
.verifyIssues();
80+
81+
CheckVerifier.newVerifier()
82+
.onFiles(mainCodeSourcesPath(CUSTOM_IV_FACTORY_DETECTION_SOURCE_PATH), mainCodeSourcesPath(STATE_RESET_TEST_FILE_SOURCE_PATH))
83+
.withCheck(new CipherBlockChainingCheck())
84+
.verifyIssues();
85+
}
6186
}

0 commit comments

Comments
 (0)