CodeQL(lgtm) + VSCode + C/C++ で静的(?)ソースコード解析をお手軽に極めたいメモ

# 背景

* レイトレーシングや機械学習などの C/C++ アプリを書いている
* 配列範囲外アクセスとかのよくある定型的なチェックの unit test 書くのがめんどい
  * 自動でいい感じにテストしたりよしなにチェックしたりしてくれるのほしい

最近 Github に CodeQL が統合(?)されるみたいなニュースがありました.

かつて(?) LGTM.com という名称でサービス(クエリ言語の名称が CodeQL)していた Semmle という会社が, github に買収となり, CodeQL が今度はサービス名となったのでしょうか.

tinyexr で lgtm 使っていたので, なんとなく ltgm というサービス(リスざるっぽいイラストのアイコン)記憶にありました.

CodeQL(or LGTM) を再訪してみます.
 
## 似たようなサービス

同様のツールとしては Coverity Scan が挙げられるでしょうか(Travis とかと連携できる).

tinyexr での Coverity scan(最近メンテしていないが)の例です
https://scan.coverity.com/projects/5827

# 情報

https://help.semmle.com/QL/learn-ql/cpp/ql-for-cpp.html

基本的に, repo にあるソースコードを, ビルドプログラム(e.g. cmake)を自動で判定し, 解析するファイル群をリストアップし, 解析してくれます.

## LGTM で解析する

lgtm にアカウント登録(github account 連携できます)して, 解析したい git repo 指定するだけです
(他人の git repo も可能)
自身の github (public) git repo の場合, github 連携しておくと, push のたびに lgtm がチェックを走らせてくれるようです.

C/C++ の場合, 一度ビルドするようなので, Makefile or cmake 設定ファイルが必要です.
細かいビルド設定は, 下記 lgtm.yaml で設定できます.

現状 Linux を想定していますが, `_MSC_VER` のコードなど, Windows 限定(or macOS) のコードをテストするには, それぞれの OS でビルドしないといけないがそこのところどうなるのかしらん?
 

### 解析するソースコードを指定する

自身のプロジェクトとは関係ない third_party のコードは解析に含めないようにしたいですよね.

git repo に `lgtm.yaml` を用意して, `path_classifiers` で行けるようですが...

https://lgtm.com/help/lgtm/customizing-file-classification

現状うまくいきませんでした...

(git push してすぐ lgtm に反映されるわけではない(数時間から半日くらいかかる)ので, 動作確認が手探りになってしまい時間がかかる)

## VSCode で CodeQL をためす

VSCode で, LGTM がやっているようなことを手元ローカルで実行できます.

## LGTM 登録

必須ではないですが, 登録しておいたら便利なので(e.g. 既存データベースをダウンロードなど), lgtm に登録していなければ登録しておきます(github account 利用可能)

## VScode での操作

https://help.semmle.com/codeql/codeql-for-vscode.html

まず extension を入れます(左のパネルに CodeQL アイコンができます)

codeql cli もインストールされます.

Ubuntu ですと以下にインストールされていました.

```
./.config/Code/User/globalStorage/github.vscode-codeql/distribution1/codeql/codeql
```


クエリサンプルなどのある vscode-codeql-starter(vscode workspace つき) を clone しておきます.

https://github.com/github/vscode-codeql-starter/


## データベースの生成

**注意**

ここがひっかかるのですが, データベース生成自体は現状 VSCode plugin では行なえません(databse upgrade はある).


lgtm.com に git repo を登録して生成してもらう(=> その後 url 指定で VSCode からダウンロード)か, 自前でコマンドラインで codeql を実行してデータベースを生成します.


とりあえず手っ取り早く lgtm からデータベースダウンロードしてみましょう.

tinyexr つかってもよろしくてよ.

https://lgtm.com/projects/g/syoyo/tinyexr/

`vscode-codeql-starter` の submodule repo に関連するデータベースも lgtm あたりからダウンロードできます(C++ のデータベースを選択する必要がある)

## CodeQL でクエリをかける.

**注意** ここもひっかかるところですが, クエリ(解析)自体はデータベースに対して行うので, git repo のソースコードは関係ない(データベースファイルさえあればよい)です!

また, `codeql-vscode-starter` repo には, クエリサンプルなどがあるだけで, 実際にクエリを走らせて試せる C++ コードはありません(正確には submodule に C++ コードサンプルあるが, いずれにせよ上記データベースのところで解説しているように, 対応する repo のデータベースを取得する必要があり, C++ コード(git repo)を直接見て解析ではない)

* データベースを選択する
* VSCode 上でクエリ(ファイル)を選択する
* コマンドパレット(`ctrl` + `shift` + `p`) or クエリファイル右クリックで, `Run Query` します!
 
![Screenshot from 2020-06-03 15-48-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/dfefb30b-e2b2-da11-5c76-6b442b7c1f50.png)





うまくいったら, このような感じで問題のあるところ(query でひっかかったもの)のリストと, 対応するソースコードを VSCode 上でブラウズできます!

上記スクショに対応する CodeQL は, 以下になります.
(codeql-vscode-starter より)

```
import cpp
import experimental.semmle.code.cpp.rangeanalysis.ArrayLengthAnalysis

from Instruction array, Length length, int delta, Offset offset, int offsetDelta
where
  knownArrayLength(array, length, delta, offset, offsetDelta) and
  array.getAUse() instanceof ArgumentOperand
select array, length, delta, offset, offsetDelt
```

クエリが複雑だと, コンパイルにそこそこ時間かかります.

また, 特にファイル名などに制約が無いクエリだと, STL ヘッダファイルなども解析してしまいます.

## CodeQL language

一見 C# っぽくも見えますが, Datalog(Prolog 系列)の方言とありました.

https://help.semmle.com/QL/ql-handbook/language.html

## まとめ

lgtm に登録して解析では, 特に面倒なことはありません.

CodeQL を手元で走らせるには, いかんせん情報が少なすぎて(現状 lgtm/semmle のページくらいしかない)手探りでめんどいです.
(ツール自体はそれなりにしっかり作ってある感がありますが)

qiita 記事も, 本記事以外ありません(2020 Jun 03 時点) :cry:

Github に統合されれば, ユーザーが増えてクエリサンプルやベストプラクティスも拡充するでしょうか.

CodeQL で脆弱性を発見すると, 最大 2,500 USD(1 クエリあたり?) がもらえる bounty もあります.

https://securitylab.github.com/bounties

(レイトレーシングや機械学習版もやってほしいな〜(e.g. 計算で NaN が出ないようにするとか))

また, CodeQL では, 特定の名前にマッチする関数を探す, みたいなのもできるので, コードリファクタリング的な用途にも使えるかもです.



## LTGM or CodeQL?

とりあえず repo をお手軽解析したければ LTGM.com を使う, 手元で走らせたい, 個別にチェックしたくなったら CodeQL を使うです.

近いうちに Github Action のような感じで github のページに統合されて, 使いやすくなるかもしれません.

## TODO

* [ ] 解析しないソースコードやファイルを指定する方法を探す
* [ ] CodeQL(のバッチ)をインタラクティブに実行し, VSCode 上で quick and fix できるようにする.
  * [ ] 作業中 git repo に対して, databse 生成とアップデートをお手軽に行う方法を探す
* [ ] レイトレーシングや機械学習に適したクエリを記述する