C/C++ ソースコードチェッカー/cppCheck/ソースをいじってみる

 クラウディア
1. ソースファイルを取得する
2. 何をチェックしてみたかったか
3. ビルドしてみる
4. ソースを読んでみる
5. ソースをいじってみる

1. ソースファイルを取得する

 ここでソースをいじってみると言っているのは 「cppcheck」 自体のソースのことです。  チェックしたい関数があって、デフォルトではチェックされない。  「cfg」 の設定のみではどうにもならなそうなので、本体のソースをいじってみることにしたのです。  「Windows」 版であれば「2.1 Windows版ダウンロード・インストール」で示しているサイトから 「zip」 形式でソースをダウンロードできます。

2. 何をチェックしたかったか

 では何をチェックしたかったかというと。  「Visual C++」 に 「SecureZeroMemory」 という関数がありまして。  いまや、「gcc」 でも非推奨になった 「bzero」 と同じ機能で。  「gcc」 では 「memset」 を使えということになっています。  似た関数に 「ZeroMemory」 というのがあるのですが、何が違うのかというと 「ZeroMemory」 はコードによっては、「Release」 でビルドするとオプティマイズアウトされることがあるらしいが、「SecureZeroMemory」 はそれがない・・・と。  つまり確実にその領域をクリアするということらしいです。  実は、「ZeroMemory」 は 「memset」 のラッパで 「SecureZeroMemory」 は 「memset_s」 のラッパであるらしい。  ということは 「memset」 も 「memset_s」 に変えるべきなんだな。  というのは置いておいて、以下のようなコードがあるとします。内容は問わないで、チェックだけに目を向けてください。

int main(int argc, char* argv[])
{
    int n;
    int* tmp = &n;

    SecureZeroMemory(tmp, sizeof(tmp));
    memset(tmp, 0, sizeof(tmp));

    return 0;
}
 これを 「cppcheck」 にかけると 「memset」 の方は

内容: Size of pointer 'tmp' used instead of size of its data.
メッセージ: Size of pointer 'tmp' used instead of size of its data. This is likely to lead to a buffer overflow. You probably intend to write 'sizeof(*tmp)'.
 てな警告が出るんですな。「sizeof(tmp)」 と書いているが、おいおい 「sizeof(*tmp)」 の間違いじゃないか?・・・と。  よくあるミスで、つい 「*」 をつけそこなっちゃっててクリアするはずの領域が消えてなかったりする。  逆に、型が 「char」 だったりしたら消してはいけない領域までクリアしてしまったりする。  「SecureZeroMemory」 も同じ事情なのですが、残念ながら 「SecureZeroMemory」 の方は警告が出てくれないのです。  実は、あるプロジェクトで 「SecureZeroMemory」 を多用していて、ついやっちゃったときに全部チェックすることになったのですが、人的作業ではたまらんわけです。  で、「cppcheck」 でなんとかならんもんかいな・・・ということです。

3. ビルドしてみる

 とりあえず、「Windows」 版のソースコードをダウンロードして、展開したら 「sln」 という拡張子があるので 「Visual Studio」 でビルド (「Visual Studio」 なので 「make」 ではないわけです) できるぞ・・・と。  「Visual Studio 2010」 でビルドしてみたら

プロジェクト ファイルに ToolsVersion="14.0" が含まれています。このツールセットが不明であるか、存在しない可能性があります。その場合は、適切なバージョンの MSBuild をインストールして解決するか、ビルドがポリシー上の理由により特定の ToolsVersion を使用するよう強制されている可能性があります。プロジェクトを ToolsVersion="4.0" として扱います。詳細については、http://go.microsoft.com/fwlink/?LinkId=291333 を参照してください。
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Platforms\x64\Microsoft.Cpp.x64.Targets(507,5): error MSB8008: 指定したプラットフォーム ツールセット (v140) はインストールされていないか無効です。サポートされている PlatformToolset 値が選択されていることを確認してください。
 てなエラーになりました。「ToolsVersion="14.0"」ってのは 「Visual Studio 2015」 のもののようなので、「Express」 をインストールしてビルドしたらうまくいきました。

warning C4389: '==': signed と unsigned の数値を比較しようとしました。
 とか、「cppcheck」 のソースが警告の出るものというのが笑えましたが・・・。

4. ソースを読んでみる

 「Size of」 だとか 「pointer」 をキーワードに探してみたら、ありました。
lib/checksizeof.cpp
 の

checkSizeofForPointerSize
 という関数がわたしの目的とする関数のようです。

5. ソースをいじってみる

 ちょっとした試行錯誤があったのですが(きちんとソースを解析してないからいかんのです) 149行目と 150行目の間に

else if (Token::simpleMatch(tok, "SecureZeroMemory (") && tok->strAt(-1) != ".") {
    variable = tok->tokAt(2);
    tokSize = variable->nextArgument();
    tokFunc = tok;
 というコードをいれてビルド。  「bin」 の下にできた

cppcheck-core.dll
cppcheck.exe
 を

C:\Program Files\Cppcheck
 に上書きして、先ほどのソースをチェックしてみたら、うまくチェックできるようになりました。
ハイスピードプラン