メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C++: ENV32-C

すべての終了ハンドラーは正常に戻らなければならない

説明

ルール定義

すべての終了ハンドラーは正常に戻らなければなりません。1

Polyspace 実装

ルール チェッカーは、"終了ハンドラーが異常終了しました" をチェックします。

すべて展開する

問題

終了ハンドラーが異常終了しましたでは登録済みの終了ハンドラーを調べます。終了ハンドラーは atexit、(WinAPI) _onexit または at_quick_exit() などの固有の関数で登録されます。プログラムで想定されている終了順序に割り込む関数が終了ハンドラーによって呼び出されると、Polyspace により欠陥が検出されます。異常終了の原因となる可能性がある関数には、exitabortlongjmp、(WinAPI) _onexit などがあります。

リスク

終了ハンドラーによってプログラムが終了される場合、未定義の動作になる可能性があります。プログラムの異常終了は、他の終了ハンドラーが呼び出されていないことを意味します。このような追加の終了ハンドラーでは、追加のクリーン アップやその他の必要な終了手順が行われる可能性があります。

修正方法

終了ハンドラーが正常終了するのを妨げる関数呼び出しを終了ハンドラー内から削除します。

例 - exit の呼び出しを含む終了ハンドラー
#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        exit(0);  //Noncompliant
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() performs additional cleanup */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0)
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

この例では、demo_install_exitabnormalhandler が 2 つの終了ハンドラー demo_exit1exitabnormalhandler を登録しています。終了ハンドラーは、登録時とは逆順に呼び出します。プログラムの終了時、exitabnormalhandler が実行され、次に demo_exit1 が実行されます。しかし、exitabnormalhandler が、プログラムの終了プロセスに割り込む exit を呼び出しています。終了ハンドラー内にこの exit があると、プログラムが安全にクリーン アップされずに終了するため、未定義の動作が発生します。

修正 — 終了ハンドラーから exit を削除

考えられる 1 つの修正方法として、終了ハンドラーが正常終了するようにします。この例では、exitexitabnormalhandler から削除し、終了プロセスが想定どおりに完了できるようにします。

#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        /* Return normally */
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() continues clean up */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0) 
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

チェック情報

グループ: 49.その他 (MSC)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.