Compare commits

...

5 Commits

  1. 5
      .gitignore
  2. 15
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java
  3. 87
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java
  4. 9
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/DynamicLibraryLoadChecker.html
  5. 13
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/DynamicLibraryLoadChecker.json
  6. 10
      sonar-keyware-plugins-java/src/test/files/DynamicLibraryLoadChecker.java
  7. 23
      sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadCheckerTest.java

5
.gitignore vendored

@ -4,10 +4,7 @@ target/
!**/src/test/**/target/ !**/src/test/**/target/
### IntelliJ IDEA ### ### IntelliJ IDEA ###
.idea/modules.xml .idea/
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws *.iws
*.iml *.iml
*.ipr *.ipr

@ -35,15 +35,8 @@ public final class RulesList {
AbsolutePathDetectorChecker.class, AbsolutePathDetectorChecker.class,
PathAndKeywordCheck.class, PathAndKeywordCheck.class,
DynamicCodeChecker.class, DynamicCodeChecker.class,
SystemFunctionChecker.class SystemFunctionChecker.class,
/*SpringControllerRequestMappingEntityRule.class, DynamicLibraryLoadChecker.class
AvoidAnnotationRule.class,
AvoidBrandInMethodNamesRule.class,
AvoidMethodDeclarationRule.class,
AvoidSuperClassRule.class,
AvoidTreeListRule.class,
MyCustomSubscriptionRule.class,
SecurityAnnotationMandatoryRule.class*/
)); ));
} }
@ -51,8 +44,6 @@ public final class RulesList {
* These rules are going to target TEST code only * These rules are going to target TEST code only
*/ */
public static List<Class<? extends JavaCheck>> getJavaTestChecks() { public static List<Class<? extends JavaCheck>> getJavaTestChecks() {
return Collections.unmodifiableList(Arrays.asList( return Collections.emptyList();
/*NoIfStatementInTestsRule.class*/
));
} }
} }

@ -0,0 +1,87 @@
package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule;
import org.sonar.java.ast.visitors.SubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*;
import org.springframework.lang.NonNull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 在动态加载库前应对输入数据进行验证确保输入数据仅能用于加载允许加载的代码库
* 判断逻辑: 当检测到函数中包含调用System.loadLibrary()方法时则认为是在加载动态库然后判断其参数是否由方法入参传递的
*
* @author GuoXin
* @date 2024/1/10
*/
@Rule(key = "DynamicLibraryLoadChecker")
public class DynamicLibraryLoadChecker extends SubscriptionVisitor {
@Override
public List<Tree.Kind> nodesToVisit() {
var nodeType = new Tree.Kind[]{Tree.Kind.METHOD};
return Arrays.asList(nodeType);
}
@Override
public void visitNode(@NonNull Tree tree) {
if (tree.is(Tree.Kind.METHOD)) {
MethodTree method = (MethodTree) tree;
var block = method.block();
if (block != null) {
// 拿到方法入参列表
var methodNames = method.parameters().stream().map((item) -> item.simpleName().name()).collect(Collectors.toSet());
// 使用方法体查看器对代码块进行遍历
block.accept(new MethodBodyVisitor(this, methodNames));
}
}
}
/**
* 该内部类用于遍历方法体中的代码块并检查是否调用了System.loadLibrary()方法并且方法参数为方法入参
*/
static class MethodBodyVisitor extends BaseTreeVisitor {
private final DynamicLibraryLoadChecker checker;
private final Set<String> methodParameters;
/**
* 构造方法
*
* @param checker 动态库加载检查器
* @param methodParameters 方法入参集合
*/
public MethodBodyVisitor(DynamicLibraryLoadChecker checker, Set<String> methodParameters) {
this.checker = checker;
this.methodParameters = methodParameters;
}
/**
* 遍历方法调用语法树节点
*
* @param tree 语法树节点
*/
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
var methodSelect = tree.methodSelect();
if (methodSelect instanceof MemberSelectExpressionTree) {
var mset = (MemberSelectExpressionTree) methodSelect;
// 判断是否调用了System.loadLibrary()
if (mset.firstToken() != null && "System".equals(mset.firstToken().text()) && "loadLibrary".equals(mset.identifier().name())) {
// 判断方法调用的参数是否是方法入参,在System.loadLibrary()函数仅接受一个参数
var exp = tree.arguments().get(0);
if (exp.is(Tree.Kind.IDENTIFIER)) {
var id = (IdentifierTree) exp;
if (methodParameters.contains(id.name())) {
// 报告问题
checker.context.reportIssue(checker, tree, "在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库");
}
}
}
}
}
}
}

@ -0,0 +1,9 @@
<h2>在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库</h2>
<p>在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库。</p>
<pre>
</pre>
<h2>合规解决方案</h2>
<pre>
</pre>

@ -0,0 +1,13 @@
{
"title": "在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"28suo"
],
"defaultSeverity": "Minor"
}

@ -0,0 +1,10 @@
// 在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库
class DynamicLibraryLoadCheckerExample {
public void loadLibrary(String libraryName, int number) {
String abc = "bac";
System.loadLibrary("/path/to/your/library");
System.loadLibrary(libraryName); // Noncompliant {{在动态加载库前对输入数据进行验证,确保输入数据仅能用于加载允许加载的代码库}}
}
}

@ -0,0 +1,23 @@
package com.keyware.sonar.java.rules.checkers;
import com.keyware.sonar.java.utils.FilesUtils;
import org.junit.jupiter.api.Test;
import org.sonar.java.checks.verifier.CheckVerifier;
/**
* 在动态加载库前对输入数据进行验证 单元测试类
*
* @author GuoXin
* @date 2024/1/10
*/
public class DynamicLibraryLoadCheckerTest {
@Test
public void test() {
CheckVerifier.newVerifier()
.onFile("src/test/files/DynamicLibraryLoadChecker.java")
.withCheck(new DynamicLibraryLoadChecker())
.withClassPath(FilesUtils.getClassPath("target/test-jars"))
.verifyIssues();
}
}
Loading…
Cancel
Save