linux 命令行使用codeql


CodeQL

CodeQL是一個代碼檢查工具,會根據開發者編寫的代碼生成數據庫,之后開發者通過編寫ql腳本查找代碼中的問題。原本似乎是semmle(?)的產品,后來被github收購了,所以現在實際上應該算是github官方的東西(但是github現在又是微軟的了...)。

以C++為例,雖然gcc編譯器本身就會對代碼做語法檢查,保證代碼沒有錯誤,但是在每個項目中可能會有一些約定俗成的規則,比如在某個函數中不能調用某個函數這樣的規則,此時就可以通過ql腳本制定一個自定義規則,codeql會篩查出來符合規則的代碼。並且可以輸出為csv文件。

CodeQL支持vscode編輯器,網上幾乎所有的使用教程都是使用VSCode編輯器運行CodeQL的,但是我的使用環境是服務器,使用vim開發,並不能使用VSCode,所以研究了一下怎么直接在命令行中使用CodeQL對代碼進行檢查。

相關參考:

建議先通過vscode配置好一個codeql方便學習語法,然后再命令行中使用。

概述

codeql分成兩部分,一部分是CodeQL CLI,另一部分就是它自帶的qll庫了 可以理解為,前者是解釋器控制台(編譯器),后者是庫文件,相當於C語言中stdio.h的存在,提供一些常用的類和方法

Getting started with the CodeQL CLI — CodeQL (github.com)

大體使用過程分為兩步,首先生成數據庫,之后編寫ql腳本對數據庫進行查詢。

在生成數據庫這一步分為需要區別解釋型語言和編譯型語言,解釋型語言可以解析直接生成數據庫,而編譯型語言codeql需要監控編譯過程。

安裝

直接使用在線查詢(lgtm)

lgtm.com

不過這個網站訪問比較玄學,科學或者魔法你總得會一個。國內直連訪問不太穩定,經常打不開,所以建議學習的時候使用vscode

vscode使用codeql

這也是網絡上最常用的使用方式,不過根據網上的操作方式給我弄得很懵逼,如果會英文的話,直接看官方文檔比較好。

Setting up CodeQL in Visual Studio Code — CodeQL (github.com)

下載

在vscode里面安裝插件

image-20211214144535144

然后點擊這個測試,新版會問你要不要安裝CLI,點擊YES之后就會自動開始下載 (我第一次使用的時候是沒有提示下載的,如果沒有提示需要自己下載,參考網上別的教程,唯一需要注意的就是需要把庫文件給放到CLI目錄(codeql命令所在目錄)里,改名。否則運行腳本的時候會提示找不到庫文件)

image-20211214145232989

image-20211214145217635

到此CLI就安裝好了 它自己安裝的路徑C:\Users\用戶名\AppData\Roaming\Code\User\globalStorage\github.vscode-codeql\distribution1\codeql

庫文件

(通過vscode自動安裝就不需要手動下載庫文件了)
然后下載庫文件,github/codeql: CodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security (code scanning), LGTM.com, and LGTM Enterprise

或者把這個倉庫克隆下來也行 (我給放到了 D:/codeql/codeql_repo)

測試

下載現成的數據庫,用來測試環境是不是正常的,數據庫位置無所謂,解壓出來

uboot數據庫:https://downloads.lgtm.com/snapshots/cpp/uboot/u-boot_u-boot_cpp-srcVersion_d0d07ba86afc8074d79e436b1ba4478fa0f0c1b5-dist_odasa-2019-07-25-linux64.zip

vscode打開文件夾 D:/codeql/codeql_repo

然后選擇 From a folder選擇到剛才解壓的數據庫

image-20211214152858144

然后在vscode的資源管理器里面打開路徑 cpp/ql/src/ 這里面都是一些例子代碼,比如下面我運行了 Likely Bugs/ReturnConstType.ql 只需要在ql文件里面右鍵選擇 CodeQL: Run Query

image-20211214153533837

image-20211214150708924

linux控制台運行

這里使用的版本是 2.6.3版本,經過測試centos6.8及以下是不能直接運行的 (但是你可以安裝docker然后在centos7.9的容器中運行)

下載

通過Releases · github/codeql-cli-binaries下載,linux下載codeql-linux64.zip

解壓到~/codeql/codeql

下載或者克隆庫文件 github/codeql: CodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security (code scanning), LGTM.com, and LGTM Enterprise

放到 ~/codeql/codeqlrepo

這里需要注意的是,庫文件必須在cli的同級目錄或者子目錄 否則會找不到包

安裝

可以建立一個軟鏈到/usr/bin/

然后執行 codeql --version 沒有問題就好了

創建數據庫

相關的官方說明:Creating CodeQL databases — CodeQL (github.com)

對於C++來說,命令如下

codeql database create testdb/ --language=cpp --command="g++ c.cpp"

--command參數指定了正常編譯的時候需要執行的命令,可以是make -j20這樣的命令

--language 參數指定了需要生成數據庫的語言,具體可以是什么參看上面相關官方說明的連接里面

如果修改了代碼想要重復生成數據庫,可以添加--overwrite參數覆蓋數據庫

所以,生成C++數據的命令可以是codeql database create testdb/ --overwrite --language=cpp --command="make -j20"

[st@local ~]$ codeql database create testdb/ --language=cpp --command="g++ c.cpp"
Initializing database at /home/st/testdb.
Running build command: [g++, c.cpp]
Finalizing database at /home/st/testdb.
Successfully created database at /home/st/testdb.

命令執行完成之后可以看到當前目錄下面有一個testdb文件夾,這個就是codeql的數據庫

編寫QL查詢數據庫

相關官方說明:database analyze — CLI manual (github.com)

建議在~/codeql/codeqlrepo/cpp/ql/src/創建一個文件夾比如work,在這個文件夾中編寫自己的ql代碼

一個簡單的例子

/**
 * @name AllFunction
 * @kind problem
 * @id cpp-test
*/

import cpp
from Function f
select f, "name: " + f.getName()

這個ql腳本會把所有的函數列舉出來,

運行這個腳本使用命令如下

codeql database analyze testdb --rerun --format=csv --output=c.csv ./codeql_repo/cpp/ql/src/work/allfun.ql

--rerun 表示重復查詢,默認情況下codeql會直接使用數據庫中緩存的結果,會導致修改ql腳本之后再運行的結果不正確,所以強烈建議加上這個參數

--format=csv表示指定輸出結果文件的格式,一般控制台的話輸出csv格式就好了,還有其他格式參考上面給出的相關官方說明

--output=c.csv把結果輸出到c.csv文件里面

完整參數解釋database analyze — CLI manual (github.com)

運行結果

image-20211214165409786

簡單解釋

首先貼出來對於ql文件的官方說明: About CodeQL queries — CodeQL (github.com)

注釋風格是C/C++的風格,上面代碼中注釋的部分被稱之為query metadata,相關說明: Metadata for CodeQL queries — CodeQL (github.com)

不過需要注意的是,文檔比較老舊,所以只能作為參考,比如文檔說@kind是可選項,但是經過測試,腳本在控制台下執行的時候,是必須的,否則運行不起來(vscode里面跑的時候確實是可選的)。此外,雖然說文檔里說@kind類型只有problempath-problem兩個,但是我看例子代碼里面還有table,所以說,最好是文檔配合位於codeql庫文件/cpp/ql/src/里面的例子代碼一起看比較好。

import cpp表示導入C++相關的庫文件

from Function f 按照C++的思想來說就是聲明一個變量,如果類比sql語句,就相當於選定了一張表,可以理解為f是一個集合,里面是數據庫中所有的函數。

select 輸出結果,如果上面是@kind problem,那么select就必須是兩個參數。否則會報錯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM