goto fail; をコンパイル時に検出する

日本語の記事が見当たらないので書きます。iOSSSLのバグは、コンパイル時に検出できます。警告オプション -Wunreachable-code をつけて clang でコンパイルすれば良いだけです。

バグの原因

このバグの原因は、意図しない場所に goto 文が書かれていたため、重要な処理をスキップしてしまうというものです。
こちらのブログ記事で紹介されてますが、単純化すると以下のようになります。

error_code important_function()
{
    error_code err;

    // ...

    if (err = some_function(...))
        goto fail;
    if (err = some_function2(...))
        goto fail;
        goto fail; // (A)

    // 重要な処理 (B)
    // ...

fail:
    // 後始末
    // ...

    return err;
}

ご覧の通り、goto 文 (A) で常に重要な処理をスキップしています。err は (B) で失敗を表す値になり得るので、important_function は失敗するはずなのに、実際には成功を表す値を返す場合があります。ここの632行目ですね……。

対策

元コードについてはそもそも、 if 文の statement 部を compound-statement にした方がいいとか、きちんとインデントした方がいいとか突っ込みどころは多いんですが、ひとまず措きます。そういったことは考えず、バグは機械的に見つけたいものです。決して実行されないコードが関数内にあるという事実は、バグの存在を強く示唆しますね。上のコードだと、実行されないコードがあることはコンパイル時に分かるはずです。

上で紹介したブログ記事にも書かれてますが、clang で -Wunreachable-code をつけてコンパイルすれば警告されます。残念ながら -Wall をつけただけでは -Wunreachable-code は有効にはなりませんので明示的につける必要があります。