CERT.EXIT.HANDLER_TERMINATE

exit ハンドラーの登録関数から exit 関数を呼び出さないでください。

CERT.EXIT.HANDLER_TERMINATE チェッカーは、exit ハンドラー関数から exit 関数を呼び出すコードにフラグを立てます。このチェッカーは、CERT 規則 ENV32-C で指定されているように、exit() と quick_exit() の呼び出しに加えて、longjmp() の呼び出しにもフラグを立てます。

このチェッカーは、exit ハンドラーとそれをインストールする呼び出しが同じコンパイル単位にある場合にのみフラグを立てることに注意してください。

脆弱性とリスク

exit 関数をさらに呼び出した exit ハンドラー関数から exit 関数を呼び出すと、ネストした呼び出しが発生する可能性があり、exit 関数をネストして呼び出す動作は未定義です。

軽減と防止

すべての exit ハンドラーが正常に戻ることを確認します。

脆弱コード例

コピー
    #include <stdlib.h>

    void exit1(void)
    {
        return;
   }

    void exit2(void)
    {
       extern int some_condition;
       if (some_condition) {
           exit(0);
       }
       return;
   }

   int main(void)
   {
       if (atexit(exit1) != 0) {
           /* Handle error */
       }
       if (atexit(exit2) != 0) {
           /* Handle error */
       }
       return 0;
   }    

この非準拠のコード例では、exit が exit ハンドラー関数から呼び出され、その exit ハンドラー関数「exit2」は正常に戻されないため、12 行目で欠陥 CERT.EXIT.HANDLER_TERMINATE にフラグを立てます。

修正コード例

コピー
   #include <stdlib.h>
  
   void exit1(void)
   {
       /* ...Cleanup code ...*/
       return;
   }

   void exit2(void)
  {
      extern int some_condition;
      if (some_condition) {
          /* ...More cleanup code ...*/
      }
      return;
  }

  int main(void)
  {
      if (atexit(exit1) != 0) {
          /* Handle error */
      }
      if (atexit(exit2) != 0) {
          /* Handle error */
      }
      /* ...Program code ...*/
      return 0;
  }

前のスニペットの問題を修正しました。上記の準拠した例では、exit ハンドラー関数「exit1」と「exit2」は両方とも正常に戻っています。

外部参考資料