diff --git a/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.java b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.java new file mode 100644 index 0000000..3f50a22 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +package com.keyware.sonar.cxx.rules.checkers; + +import com.sonar.cxx.sslr.api.AstNode; +import com.sonar.cxx.sslr.api.Grammar; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.cxx.parser.CxxGrammarImpl; +import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault; +import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.cxx.squidbridge.checks.SquidCheck; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * TODO IntegerCountVerifyChecker + * + * @author RenFengJiang + * @date 2024/1/18 + */ +@Rule(key = "IntegerCountVerifyChecker", name = "來自用戶的整型数据进行算术运算应进行验证", description = "对来自用户的整形数据作算术运算前进行验证,确保运算结果不会溢出", priority = Priority.INFO, tags = {"28suo"}) +@ActivatedByDefault +@SqaleConstantRemediation("5min") +public class IntegerCountVerifyChecker extends SquidCheck { + @Override + public void init() { + // 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点 + this.subscribeTo( + CxxGrammarImpl.functionBody + ); + } + + /** + * 访问AST节点 + * + * @param node 要处理的AST节点,该节点类型为通过subscribeTo方法订阅的类型 + */ + @Override + public void visitNode(@Nonnull AstNode node) { + //存放用户输入的整形变量 + List cinList = verdictUserParam(node); + //获取到if判断中的参数 + Map map = ifParam(node); + //获取到算术表达式 + List descendants = node.getDescendants(CxxGrammarImpl.multiplicativeExpression); + descendants.addAll(node.getDescendants(CxxGrammarImpl.additiveExpression)); + for (AstNode desc:descendants) { + //获取到算术表达式中的参数 + List children = desc.getChildren(); + for(AstNode dren:children){ + //过滤掉无用的参数 + if("IDENTIFIER".equals(dren.getName())){ + //判断是否存在于用户传递的参数集合中 + if(cinList.contains(dren.getTokenValue())){ + //判断是否进行过校验 + if(map.containsKey(dren.getTokenValue())){ + Integer integer = map.get(dren.getTokenValue()); + //判断校验是否在算术之前 + if(integer > dren.getTokenLine()){ + getContext().createLineViolation(this,"來自用戶的整型数据进行算术运算应进行验证",dren); + } + }else { + getContext().createLineViolation(this,"來自用戶的整型数据进行算术运算应进行验证",dren); + } + } + } + } + } + } + + //获取用户输入的整形变量 + public static List verdictUserParam(AstNode node){ + //存放整型变量 + List lists = new ArrayList<>(); + //存放用户输入的整形变量 + List cinList = new ArrayList<>(); + //获取所有的语句 + List statList = node.getDescendants(CxxGrammarImpl.statement); + for (AstNode stList : statList){ + //判断是否是整形变量 + if("int".equals(stList.getTokenValue())){ + List listDescendants = stList.getDescendants(CxxGrammarImpl.initDeclarator); + for(AstNode desc : listDescendants){ + lists.add(desc.getTokenValue()); + } + //判断是否是std类型 + }else if("std".equals(stList.getTokenValue())){ + //获取到方法名称 + AstNode firstDescendant = stList.getFirstDescendant(CxxGrammarImpl.qualifiedId); + List children = firstDescendant.getChildren(); + for(AstNode desc : children){ + //判断是否是用户输入方法 + if("cin".equals(desc.getTokenValue())){ + //获取用户输入中的参数变量 + AstNode descendant = stList.getFirstDescendant(CxxGrammarImpl.shiftExpression); + List descendantChildren = descendant.getChildren(); + for(AstNode dant:descendantChildren){ + if("IDENTIFIER".equals(dant.getName())){ + //判断输入的是否是整形变量 + if(lists.contains(dant.getTokenValue())){ + cinList.add(dant.getTokenValue()); + } + } + } + } + } + } + } + return cinList; + } + + public static Map ifParam(AstNode node){ + Map map = new HashMap<>(); + //选择节点语句 + List nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement); + for (AstNode astNode:nodeDescendants) { + //判断节点是不是if节点 + if("if".equals(astNode.getToken().getValue())){ + //获取其中的参数 + List astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList); + astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition)); + for (AstNode expr:astNodeList) { + map.put(expr.getTokenValue(),expr.getTokenLine()); + } + //判断第二种情况获取到if里面的参数 + if(astNodeList.size() == 0){ + List astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression); + for (AstNode as:astNodes) { + List children = as.getChildren(); + for (AstNode chil:children) { + map.put(chil.getTokenValue(),chil.getTokenLine()); + } + } + } + } + } + return map; + } + + +} diff --git a/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyCheckerTest.java b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyCheckerTest.java new file mode 100644 index 0000000..42b290f --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyCheckerTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +package com.keyware.sonar.cxx.rules.checkers; + +import com.keyware.sonar.cxx.CxxFileTesterHelper; +import org.junit.jupiter.api.Test; +import org.sonar.cxx.CxxAstScanner; +import org.sonar.cxx.squidbridge.api.SourceFile; +import org.sonar.cxx.squidbridge.checks.CheckMessagesVerifier; + +import java.io.IOException; + +/** + * TODO IntegerCountVerifyCheckerTest + * + * @author RenFengJiang + * @date 2024/1/18 + */ +public class IntegerCountVerifyCheckerTest { + + @Test + public void checkTest() throws IOException { + var checker = new IntegerCountVerifyChecker(); + var tester = CxxFileTesterHelper.create("IntegerCountVerifyChecker.cc"); + SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); + CheckMessagesVerifier.verify(file.getCheckMessages()) + .next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证") + .next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证") + .noMore(); + } +} diff --git a/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.cc b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.cc new file mode 100644 index 0000000..7f19d4f --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.cc @@ -0,0 +1,14 @@ +#include +int main() { + int num1, num2; + // 输入两个整数 +// std::cout << "请输入两个整数:"; + std::cin >> num1 >> num2; + // 执行算术运算并打印结果 +// if(num1 > 0){ +// } + std::cout << "两数之和:" << num1 + num2 << std::endl; +// std::cout << "两数之差:" << num1 - num2 << std::endl; +// std::cout << "两数之积:" << num1 * num2 << std::endl; + return 0; +} \ No newline at end of file