专栏首页Android开发实战IOS静态代码扫描--分析与总结

IOS静态代码扫描--分析与总结

IOS静态代码扫描--分析与总结

为了进一步加强代码质量,规范并减少代码缺陷,静态代码扫描是上过环节中必不可少的一部分。大多数都希望通过不同的途径提前发现日常测试中难发现的问题。

然而iOS静态代码扫描工具有不少,它们都有什么不同?我应该选哪一个?因此,本文主要针对主流的几个工具,对同步助手的代码进行扫描,并分析对比它们的扫描结果,再敲定后续的接入计划。

该文章从以下几部分进行阐述,可按需阅读:

一、工具介绍 二、扫描能力对比 三、使用问题总结

01

工具介绍

主流的扫描工具:coverity、infer、clang、oclint

  • 1、coverity

Coverity是检测和解决C、C++、Java和C#源代码中最严重的缺陷的领先的自动化方法。它将基于布尔可满足性验证技术应用于源代码分析引擎,分析引擎利用其专利的软件DNA图谱技术和meta-compilation技术,综合分析源代码、编译构建系统和操作系统等可能使软件产生的缺陷。但这里要注意的是Coverity检测是收费的。

  • 2、clang

Clang作为LLVM编译器框架的前端,最主要的任务是词法分析、语法分析,中间代码生成。源代码通过clang语法分析后,生成了语法分析树(AST)后,可作为静态分析工具对AST进行分析。

Clang命令行调用方法:

(1)下载clang:

http://clang-analyzer.llvm.org/

(2)命令行cd到项目代码所在目录:

$ cd /path

(3)使用clang扫描,命令开头为clang的scan-build所在目录:

$/Users/admin/tools/analyzer/bin/scan-build -vxcodebuild -target QQPimPro -configuration Developer

(4)可以看到生成报告在指定目录下

  • 3、infer

Infer是Facebook开源的用来执行增量分析的一款静态分析工具,由OCaml语言编写的infer目前能检测出空指针访问、资源泄露以及内存泄露,可对C、Java和Objective-C代码进行检测。

Infer命令行调用方法:

安装python 2.7:MAC自带;

安装infer:brew install infer

  • 4、oclint

Oclint是针对C、C++和Objective C代码的静态扫描分析工具,可以和xcode、xcodebuild、xctool等集成,使用命令行方式生成分析报告。这里主要使用oclint对xcodebuild产生的log进行分析,获取相关数据以后生成html文件。

Oclint命令行调用方法:

下载oclint:https://github.com/oclint/oclint/releases(这里注意下,oclint release目前最高0.13 下载releases版本或者使用brew install oclint则不能安装最新版本,在mac 10.14+上无法执行,需要手动进行编译,编译很简单,见下图) http://docs.oclint.org/en/stable/intro/build.html

一、环境配置

需要安装oclintxcpretty

1、安装oclint

方法一:brew安装

命令行执行:

$brew tap oclint/formulae
$brew install oclint

方法二:安装包安装

(1)进入到github上,下载最新(当前为oclint-0.13-x86_64-darwin-16.7.0.tar.gz)安装包,解压出来为oclint-0.13,放到如下目录:/Users/layne/OCLint,即路径为/Users/layne/OCLint/oclint-0.13。 (2)将oclint添加到环境变量。vim打开~/.bash_profile(若没有则创建),添加如下代码:

OCLINT_HOME=/Users/layne/OCLint/oclint-0.13
 export PATH=$OCLINT_HOME/bin:$PATH

终端执行:

 $oclint
出现如下内容证明没问题:
oclint: Not enough positional command line arguments specified!
 Must specify at least 1 positional argument: See: oclint -help

方法三:源码安装 (若要自定义规则,则必须使用源码方式安装,后边会说到具体方法。)

1、安装CMake和Ninja

brew install cmake ninja

CMake和Ninja是代码编译工具,因此必须要先安装。 2、从github上下载oclint源码,解压之后重命名为oclint-0.13,然后放到如下目录(随意):/Users/layne/OCLint,最终为/Users/layne/OCLint/oclint-0.13 3、打开终端进入到/Users/layne/OCLint/oclint-0.13/oclint-scripts

cd /Users/layne/OCLint/oclint-0.13/oclint-scripts

然后执行:

./make

之后就开始下载和编译,不过时间会比较长(40min左右),且还必须能够爬出去才可以。成功之后会有如下路径:/Users/layne/OCLint/oclint-0.13/build/oclint-release,这个就是oclint的路径。 4、添加oclint到环境变量。执行:

vim ~/.bash_profile

将如下内容写入:

OCLINT_HOME=/Users/layne/OCLint/oclint-0.13/build/oclint-release
export PATH=$OCLINT_HOME/bin:$PATH

保存退出。重启终端之后在终端执行:oclint --version,出现如下内容:

LLVM (http://llvm.org/):
LLVM version 5.0.0svn-r.320669
Optimized build.
Default target: x86_64-apple-darwin17.3.0
Host CPU: broadwell

OCLint (http://oclint.org/):
OCLint version 0.13.
Built Dec 14 2017 (16:03:48).

至此oclint安装成功。

2、安装xcpretty

 gem install xcpretty

说明:这里安装的xcpretty是最新版,github上的oclint源码应该是针对最新版的xcpretty进行了兼容。为什么这么说呢?因为我一开始是采用的方法二安装的oclint,运行oclint现成的规则没有问题。之后想要自定义规则,但是方法三又太麻烦了,于是我就偷懒从网上下载了别人事先编译好的oclint-0.12(这里说的"编译好的oclint"保留了当初编译的“现场”,可以进行自定义规则,而方法二中的是“干净“的oclint),然后进行自定义规则,可是跑起来一直报错(形如"/usr/sh fail with exit code 1")。于是乎我不得不用oclint源码重新编译一遍,再运行的时候就没有错误了。

二、xcode配置

以项目LayneStudy为例。

1、创建Aggregate类型target

打开LayneStudy项目,new一个新的target,类型选择Aggregate,命名为OCLint,确定。说明:在xcode9中,Aggregate类型在Cross-platform等目录下(而非iOS、watchOS、macOS等目录下)。

2、编写shell脚本

(1)选择target OCLint,在build phases里添加New Run Script Phase。在框里输入如下脚本代码:

 chmod -R 777 $SRCROOT/oclint
 $SRCROOT/oclint/oclint.sh

(2)编写脚本oclint.sh,内容如下:

source ~/.bash_profile
 #获取项目路径
 PROJECT_DIR=$(cd `dirname $0`;cd ..;pwd)
 cd ${PROJECT_DIR}

 buildPath="${PROJECT_DIR}/oclint/build"
 compilecommandsJsonFolderPath="${PROJECT_DIR}/oclint"
 compilecommandsJsonFilePath="${PROJECT_DIR}/oclint/compile_commands.json"

 rm -rf "$compilecommandsJsonFolderPath/build"

 xcodebuild SYMROOT=$buildPath | xcpretty -r json-compilation-database -o $compilecommandsJsonFilePath

 cd $compilecommandsJsonFolderPath

 oclint-json-compilation-database -- -report-type xcode \
 -rc CYCLOMATIC_COMPLEXITY=10 \
 -rc LONG_CLASS=1000 \
 -rc LONG_METHOD=50 \
 -rc LONG_LINE=140 \
 -rc LONG_VARIABLE_NAME=30 \
 -rc SHORT_VARIABLE_NAME=1 \
 -rc MAXIMUM_IF_LENGTH=5 \
 -rc MINIMUM_CASES_IN_SWITCH=2 \
 -rc NCSS_METHOD=30 \
 -rc NESTED_BLOCK_DEPTH=5 \
 -rc TOO_MANY_METHOD=30 \
 -rc TOO_MANY_PARAMETERS=5 \
 -max-priority-1 0 \
 -max-priority-2 5 \
 -max-priority-3 10

将oclint.sh放到项目根目录下的oclint文件夹中(要先创建oclint文件夹)。最终目录结构如下:

 ../LayneStudy.xcodeproj
 ../LayneSutdy
 ../oclint
 ../oclint/oclint.sh

3、执行

回到xcode,scheme选择OCLint,command+B,编译完成之后xcode则出现各种警告,证明你成功了。

补充:

①若出现python错误,则通过设置环境变量使alias python=python3,即使用最新的python。 ②若出现/Library/Ruby/Gems/2.3.0/gems/xcpretty-0.3.0/lib/xcpretty/parser.rb:434:in `===': invalid byte sequence in US-ASCII (ArgumentError) ”这种错误,则是编码问题:在~/.bash_profile中设置编码:

export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

02

扫描能力对比

在未加任何过滤规则的情况下,四个工具对同一份代码进行扫描,并与开发童鞋一起对扫描结果进行了初步筛选和整理:

  • (1)准确率:coverity > infer >clang > oclint;
  • (2)coverity扫描维度更多、发现问题更精准;infer、clang能发现部分coverity未发现的问题,但误报率较高,可作为补充扫描;但这里要说的是coverity是收费的,并且价格还不算便宜
  • (3)infer发现的大部分较为准确(可进行缺陷扫描)
  • (4)oclint扫描出的问题数量最多,但大多是开发不关注的问题,可过滤特定结果类型关注,更适合作为扫描代码复杂度的工具。(但对于代码规范这种定制化较高的需求,使用oclint还是不错的选择)

ps:这里提一下 Xcode提供了一个Analyze功能其实就是集成的clang编译扫描

03

使用问题总结

01

1、缺少证书问题

Build代码的时候可能会遇到缺少了部分证书的问题,因此命令行调用时使用了developer模式,可忽略部分证书问题;

具体命令如下:

xcodebuild  build -workspace "${project_name}.xcworkspace" -scheme ${scheme}  -configuration Release  -sdk iphonesimulator COMPILER_INDEX_STORE_ENABLE=NO

02

2、oclint源码编译

由于oclint是基于LLVM编译器框架,基于python进行的编译,在下载内容的过程中需要科学上网,修改编译代码不是一件可取的事情,如果没能力 还是老老实实用别人编译好的吧

03

xcpretty安装

oclint和infer都需要xcpretty,所以要安装xcpretty

本文分享自微信公众号 - 喘口仙氣(gh_db8538619cdd),作者:Anymarvel

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 堆与栈区别

    堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层...

    Anymarvel
  • Synchronized深入分析

    Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。

    Anymarvel
  • onSaveInstanceState和onRestoreInstanceState详解

    一. 作用 Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不...

    Anymarvel
  • OC静态代码检测方案

    xcode工具其实本身就包含了静态代码分析功能,打开项目后,可通过菜单Product->Analyze来对代码进行扫描。

    用户5521279
  • Daily Tips(Updated)

    [No.007] 解决Ubuntu16.04 字体太细发虚(表现在Chrome中浏览中文) 这个问题产生是由于Ubuntu 16.04 LTS 的默认中日韩...

    GitOPEN
  • 原 荐 基于 HTML5 Canvas 的交

    HT_hightopo
  • 老牟seo详解SEO优化中用户体验比原创度更加重要

    网站进行SEO优化过程中很多人一味的强调原创,对,原创必然有其可贵的地方,特别是在互联网抄袭泛滥的情况下,原创更加显得难能可贵。但是我们不能片面的追求原...

    jinzhuseo.com-老牟
  • 【每周一坑】疯狂的小母牛 +【解答】数据库

    有一头母牛,它每年年初生一头小母牛。每头小母牛从第 4 个年头开始,每年年初也生一头小母牛。(别问我公牛上哪去了……)请编程实现计算在第 n 年的时候,共有多少...

    Crossin先生
  • spark按某几列删除dataframe重复行

    想根据 id 和 lable 来删除重复行,即删掉 id=2 且 lable=2 的重复行。利用 distinct 无法删除

    机器学习和大数据挖掘
  • BIM+VR技术在电力行业的应用+两则应用案例

    一、BIM相关介绍 ? 1.1、BIM相关概念 BIM是英文BuildingInformationModeling的缩写,常被译为“建筑信息模型”。是以三维数...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券