🐙
CodePipelineでソース内に例外の隠蔽がないかチェックする
こんにちは。深緑です。
以前、CodePipelineでPHPの静的解析を実行するようにしました。
これをベースに、PHPのソースコード内に例外の隠蔽をしているコードがないかチェックするようにしてみます。
例外の隠蔽チェックはPHPStanでもできるのかも知れませんが、本記事を書いた時点ではPHPStanでのやり方はわからなかったのでシェルスクリプトを用いた独自の方法で実現しています。
例外の隠蔽チェックを書いたシェルスクリプトを用意する
ソース内にこんな例外処理が複数あるとします。
下側のソースは例外を再度throwしてないので例外の隠蔽になってしまってるコードです。
try {
throw new \Exception();
} catch (\Throwable $th) {
throw $th;
}
try {
throw new \Exception();
} catch (\Throwable $th) {
// throw $th;
}
これらのソースコードを含むディレクトリに対し、pcre2grep
でcatchから閉じカッコ(})までを検索します。
find ./app -name "*.php" | xargs pcre2grep -Mrh 'catch.*{[\s\S]*?'} | grep -v "//"
そして、検索結果に対してcatchの数とthrowの数を取得。
それぞれの数が一致していれば隠蔽はなしでOK。
合わないのならその差が想定通り=意図したものであるということをチェックしてOK・NGを判定します。
catch=$(find ./app -name "*.php" | xargs pcre2grep -Mrh 'catch.*{[\s\S]*?'} | grep -v "//" | grep "catch" | wc -l)
throw=$(find ./app -name "*.php" | xargs pcre2grep -Mrh 'catch.*{[\s\S]*?'} | grep -v "//" | grep "throw" | wc -l)
完成系がこちらです。
concealing_exceptions.sh
#!/bin/bash
cd `dirname $0`
# catchとthrowの数が一致していないコードの内、すでに把握しているものの数
known=1
catch=$(find ./app -name "*.php" | xargs pcre2grep -Mrh 'catch.*{[\s\S]*?'} | grep -v "//" | grep "catch" | wc -l)
throw=$(find ./app -name "*.php" | xargs pcre2grep -Mrh 'catch.*{[\s\S]*?'} | grep -v "//" | grep "throw" | wc -l)
echo "catch statements found : $catch"
echo "throw statements found : $throw"
if [ $((catch)) -ne $((throw)) ]; then
echo "Number of catch and throw statements do not match"
if [ $((known)) -ne $(($catch - $throw)) ]; then
echo "Number of known exceptions do not match"
exit 1
else
echo "Number of known exceptions match"
fi
fi
echo "No problem found"
exit 0
CodeBuildで例外の隠蔽チェックを書いたシェルを呼び出すようにする
buildspec.ymlで例外の隠蔽チェックを書いたシェルスクリプトファイルを呼ぶように記載します。
buildspec.yml
version: 0.2
phases:
install:
runtime-versions:
php: 8.1
commands:
- yum install -y pcre2-tools
- composer install --working-dir=./
pre_build:
commands:
- sh ./concealing_exceptions.sh
- composer stan --working-dir=./
CodeBuildは動作環境を特に指定してないので、Amazon Linuxベースで動作します。
Amazon Linuxでpcre2grep
を使用するためにpcre2-tools
のインストールコマンドを入れています。
- yum install -y pcre2-tools
commands
でシェルスクリプトファイルを呼びます。
シェルスクリプトファイルが異常終了したら(リターンコードが0でない)ビルドはここで止まります。
- sh ./concealing_exceptions.sh
この状態でCodePipelineを実行しCodeBuildを起動させます。
ログを見るとしっかりと例外の隠蔽チェックを呼び出されていることがわかります。
Discussion