C言語で非推奨なC標準関数(例:strcpy)をコンパイルエラーにする方法

前書き

C言語は歴史の長い言語のため、非推奨関数があります。例えば、strcpy()は文字列をコピーする際にサイズチェックをしないため、バッファオーバーフローを引き起こす可能性があります。そのため、一般的には、strcpy()の代替関数としてstrcpy_s()を使用する事が推奨されています。

開発プロジェクトにおいて、「コーディング中の注意力」および「レビュー」によって、非推奨関数の混入を防ぐ事は困難です。現実的な問題として、

  • 新人やロートル(古い慣習をアップデートしない人)の参加
  • 開発ルール(使用関数の規約など)に従わない人
  • 時間的な制約によるレビューの簡素化

があります。上記の問題を解決するには、人の手を使わずにシステムが禁止関数の使用を検知する方法が望ましいです。そのような方法として、gitでは禁止関数リストをheaderファイルに書き、禁止関数を使用した場合はコンパイルエラーを起こす仕組みが導入されました。

コンパイラを利用した方法であれば、エンジニアのスキル習熟度に左右されませんし(実行はコマンドを叩くだけ)、人の目と違い検知漏れが発生しません。今まで、禁止関数を強制的にコンパイルエラーにする発想が無かったため、本記事ではその仕組みに関して説明します。

              

禁止関数リストbanned.hについて

GitHubにgit(banned.h)のオリジナルコードがあります。2019年9月7日時点で、banned.hの中身は以下の通りです。gitにおける禁止関数は、strcpy()、strcat()、strncpy()、strncat()、sprintf()、vsprintf()と定めているようです。

                                             

banned.hで使用されているBANNEDマクロについて、説明します。

上記マクロ中の##は、文字連結用の演算子です。そのため、BANNEDマクロを使用すると、sorry_func_is_a_banned_functionという文字列が生成されます。func部分には、関数名が挿入される想定で定義されています。

上記のbanned.hを確認すれば、

という形でマクロ(禁止関数リスト)を列挙している事が分かります。banned.hをインクルードしているソースコード中で、禁止関数を使用した場合はコンパイル時にエラーとなります。例えば、strcpyを含んだコードをコンパイルした場合、以下のようなエラーが出ます。

                 

禁止関数の追加例

禁止関数の追加例として、文字列を数値に変換するatoi()をbanned.hに加えて、コンパイルエラーを起こす方法を以下に示します。banned.hの変更方法(banned.h)、atoi()を呼び出すコード(main.c)、コンパイル例を順に記載します。

想定通り、”error:sorry_atoi_is_a_banned_function’ undeclared”が表示されている事がログから読み取れます。

                                

C言語の時代遅れ・非推奨な関数の調べ方

時代遅れ・非推奨な関数を調べるには、CERT(Computer Emergency Response Team)を参照する方法があります。CERTは、セキュリティインシデントに関する情報を提供しており、日本版のJPCERTも存在します。

このCERT(JPCERT)が提供する情報の中に、「非推奨関数や時代遅れの関数を使用しない 」があります。このページでは、「使用すべきではない関数」と「代替関数」がリストアップされています。まずは、このリストを参照すれば、一通りの情報は取得できます。

より網羅的に調べる場合は、CERTのテクニカルマネージャが執筆した「C/C++セキュアコーディング 第2版 」がオススメです。

                     

おすすめ