前言:
感觉很多事情不做就一直不会去做了......
在学校的“科创”活动要求下,不得不尝试发论文,
但我觉得我跟同学做的东西还是比较适合做Demo,为其他刚开始接触这个工具的童鞋提供参考......
正文:
继续在ubuntu中进行操作,一共进行三项检测:
(1)除零检验:
使用libclang的库函数
先提一下如何使用该库函数:
CXChildVisitResult visitor(CXCursor cursor,CXCursor parent,CXClientData clientData){} 所有的检测都在这个函数中,后面的工作几乎都是在这个函数中完成
这是访问CXCursor的函数,在主函数中经过
clang_visitChildren(cxc,visitor,cxda);调用后,
会按顺序访问输入的代码文件中的每一个CXCursor(在上面的文档链接中提到了,是一个高层抽象过的语法单元,包含多个token,可以递归包含),
通过return CXChildVisit_Continue 和 CXChildVisit_Recurse 来决定下一步的访问内容。
由于是类型上触发,所以关键在于匹配的位置。
匹配位置:
clang_getCursorKind(cursor)== CXCursor_BinaryOperator
clang_getCursorKind(cursor)== CXCursor_CompoundAssignOperator
一个是出现在形如a=c/b中的,
另一个是出现在形如a/=b的, 在匹配到上面的表达式后,找到/号最后面的变量(1个token),将其与0比较的判断语句插装到该语句前面
“if(b == 0){......}”
rewrite.InsertText(linesloc,judgeStr.c_str(),true,true);
不过要注意b++,++b,--b,b--这种特殊情况的处理
(2)负数开根号:
匹配位置: clang_getCursorKind(cursor) == CXCursor_CallExpr
匹配函数名为sqrt,sqrtf,sqrtl,将函数的参数处理出来,注意也处理++,--的问题
----------注意:以上两个函数在插装时都可能遇到位置不对的情况,比如源代码中if()后面没有花括号,会造成改变源码运行结果的问题,所以还要对if,else语句做单独处理,如果没有需要增加花括号
clang_getCursorKind(cursor) == CXCursor_IfStmt
---------
(3)数组越界:
以下开始使用ASTMatcher做检测,同样
匹配语句:
StatementMatcher ArraySubMatcher = arraySubscriptExpr().bind("arraySub");
StatementMatcher ArraySubRefMatcher = declRefExpr(hasParent(implicitCastExpr(hasParent(arraySubscriptExpr())))).bind("arraySubRef");
一次是为了得到当前使用的数组的每一维大小,另一次是为了得到正确的插装位置。
由于我是先做的前两个检测,所以if括号的问题已经在之前解决了,否则这边同样需要处理
(4)内存开辟与释放 对于c来说主要是malloc和free的匹配问题,需要在malloc后将该指针的信息存入一个结构体中,再在malloc和free的时候记下指针,再匹配,并在整个程序运行结束后看看是否有未释放的空间或者是否了不合法的指针
匹配语句:
//匹配到malloc()里的变量
StatementMatcher MallocVarMatcher = declRefExpr(hasParent(binaryOperator(
hasOperatorName("="),
hasRHS(cStyleCastExpr(has(callExpr(has(declRefExpr(to(functionDecl(hasName("malloc")))))))))))).bind("mallocVar");
//匹配到malloc()那个二元表达式
StatementMatcher MallocMatcher = binaryOperator(
hasOperatorName("="),
//hasLHS(anything()),
hasRHS(cStyleCastExpr(has(callExpr(has(declRefExpr(to(functionDecl(hasName("malloc")))))))))).bind("malloc");
//匹配到直接初始化的malloc()
DeclarationMatcher Malloc2Matcher = varDecl(has(cStyleCastExpr(has(callExpr(has(declRefExpr(to(functionDecl(hasName("malloc")))))))))).bind("malloc2");
//has(cStyleCastExpr(has(callExpr(declRefExpr(to(functionDecl(hasName("malloc"))))))))).bind("malloc2");
//匹配到free()的表达式
StatementMatcher FreeMatcher = callExpr(has(declRefExpr(to(functionDecl(hasName("free")))))).bind("free");
//匹配到free()里的变量
StatementMatcher FreeVarMatcher = declRefExpr(hasParent(implicitCastExpr(hasParent(implicitCastExpr(hasParent(callExpr(has(declRefExpr(to(functionDecl(hasName("free")))))))))))).bind("freeVar");
同样是一个用于匹配,一个用于找到插装位置。
先写这么多,代码之后会放出。
已经上传github: