|
16 | 16 | */ |
17 | 17 | package org.sonar.java.checks.security; |
18 | 18 |
|
| 19 | +import java.util.HashSet; |
19 | 20 | import java.util.Objects; |
| 21 | +import java.util.Set; |
20 | 22 | import java.util.stream.Stream; |
21 | 23 | import javax.annotation.Nullable; |
22 | 24 | import org.sonar.check.Rule; |
|
30 | 32 | import org.sonar.plugins.java.api.tree.IdentifierTree; |
31 | 33 | import org.sonar.plugins.java.api.tree.MemberSelectExpressionTree; |
32 | 34 | import org.sonar.plugins.java.api.tree.MethodInvocationTree; |
| 35 | +import org.sonar.plugins.java.api.tree.MethodTree; |
33 | 36 | import org.sonar.plugins.java.api.tree.NewClassTree; |
| 37 | +import org.sonar.plugins.java.api.tree.ReturnStatementTree; |
34 | 38 | import org.sonar.plugins.java.api.tree.Tree; |
35 | 39 | import org.sonar.plugins.java.api.tree.VariableTree; |
36 | 40 |
|
@@ -244,4 +248,77 @@ private static Stream<MethodInvocationTree> findConstructingMethods(ExpressionTr |
244 | 248 | return Stream.concat(initializerStream, reassignments); |
245 | 249 | } |
246 | 250 | } |
| 251 | + |
| 252 | + /** |
| 253 | + * Collects all methods that construct IV byte arrays in a secure way. |
| 254 | + * After applying this visitor to a class tree, {@link SecureByteArrayFactoryFinder#producesSecureBytesArray(MethodInvocationTree)} can |
| 255 | + * be used to check whether the invocation of a method belonging to that tree will return such a secure array. |
| 256 | + */ |
| 257 | + private static class SecureByteArrayFactoryFinder extends BaseTreeVisitor { |
| 258 | + private @Nullable MethodTree currentMethodTree = null; |
| 259 | + private final Set<String> secureByteArrayFactories = new HashSet<>(); |
| 260 | + private final SecureByteArrayGeneratorDetector secureByteArrayGeneratorDetector = new SecureByteArrayGeneratorDetector(); |
| 261 | + |
| 262 | + public boolean producesSecureBytesArray(MethodInvocationTree methodInvocation) { |
| 263 | + return secureByteArrayFactories.contains(methodInvocation.methodSymbol().signature()); |
| 264 | + } |
| 265 | + |
| 266 | + public void clear() { |
| 267 | + secureByteArrayFactories.clear(); |
| 268 | + } |
| 269 | + |
| 270 | + @Override |
| 271 | + public void visitMethod(MethodTree tree) { |
| 272 | + // There is no need to explore methods that do not even produce IV byte arrays |
| 273 | + if (doesNotReturnByteArray(tree) |
| 274 | + // We do not track nested methods |
| 275 | + || currentMethodTree != null) { |
| 276 | + return; |
| 277 | + } |
| 278 | + |
| 279 | + currentMethodTree = tree; |
| 280 | + super.visitMethod(tree); |
| 281 | + currentMethodTree = null; |
| 282 | + } |
| 283 | + |
| 284 | + @Override |
| 285 | + public void visitReturnStatement(ReturnStatementTree tree) { |
| 286 | + super.visitReturnStatement(tree); |
| 287 | + if (currentMethodTree == null) { |
| 288 | + return; |
| 289 | + } |
| 290 | + |
| 291 | + var returnedExpression = tree.expression(); |
| 292 | + if (returnedExpression == null) { |
| 293 | + return; |
| 294 | + } |
| 295 | + |
| 296 | + if (secureByteArrayGeneratorDetector.isDynamicallyGenerated(returnedExpression)) { |
| 297 | + markAsSecureFactory(); |
| 298 | + return; |
| 299 | + } |
| 300 | + |
| 301 | + var isSecureBytesArray = SecureInitializationFinder |
| 302 | + .forIvBytesExpression(returnedExpression) |
| 303 | + .appliesSecureInitialization(currentMethodTree); |
| 304 | + |
| 305 | + if (isSecureBytesArray) { |
| 306 | + markAsSecureFactory(); |
| 307 | + } |
| 308 | + } |
| 309 | + |
| 310 | + private void markAsSecureFactory() { |
| 311 | + Objects.requireNonNull(currentMethodTree); |
| 312 | + secureByteArrayFactories.add(currentMethodTree.symbol().signature()); |
| 313 | + } |
| 314 | + |
| 315 | + private static boolean doesNotReturnByteArray(MethodTree methodTree) { |
| 316 | + var returnType = methodTree.returnType(); |
| 317 | + if (returnType == null) { |
| 318 | + return false; |
| 319 | + } |
| 320 | + |
| 321 | + return !"byte[]".equals(returnType.symbolType().fullyQualifiedName()); |
| 322 | + } |
| 323 | + } |
247 | 324 | } |
0 commit comments