メインコンテンツ

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

errno の未チェック

関数呼び出し後のエラー状態について、errno をチェックしていない

説明

この欠陥は、エラー状態を示すように errno を設定する関数を呼び出しても、errno がチェックされなかった場合に発生します。このような関数の場合、エラーが発生したかどうかを判断するための唯一信頼できる方法は errno をチェックすることです。

エラーで errno を設定する関数には次のものがあります。

リスク

エラーなしで関数呼び出しが完了したかどうかを確認するには、errno のエラー値をチェックします。

このような errno を設定する関数の戻り値はエラーを示しません。戻り値は、以下のいずれかになります。

  • void

  • エラーが発生しても、戻り値は正常に行われた呼び出しと同じ値になる可能性があります。このような戻り値をインバンド エラー インジケーターと呼びます。

エラーが発生したかどうかは、errno をチェックすることでのみ判断できます。

たとえば、strtol は文字列を long 型整数に変換して、その整数を返します。変換結果がオーバーフローする場合、この関数は LONG_MAX を返し、errnoERANGE を設定します。ただし、この関数は正常に変換が行われても LONG_MAX を返すことがあります。errno をチェックすることでのみ、エラーと正常な変換を区別することができます。

修正方法

関数を呼び出す前に、errno にゼロを設定します。

関数呼び出しの後、errno をゼロと比較して、エラーが発生したかどうかを確認します。あるいは、errno を既知のエラー インジケーター値と比較します。たとえば、strtolerrnoERANGE を設定してエラーを示します。

Polyspace® の結果のエラー メッセージには、比較できるエラー インジケーター値が示されます。

すべて展開する

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>

int main(int argc, char *argv[]) {
    char *str, *endptr;
    int base;
    
    str = argv[1];
    base = 10;
    
    long val = strtol(str, &endptr, base);
    printf("Return value of strtol() = %ld\n", val);
}

errno をチェックしないで strtol の戻り値を使用しています。

修正 — 呼び出し後に errno をチェック

strtol を呼び出す前に、errno にゼロを設定します。strtol 呼び出し後、戻り値については LONG_MIN または LONG_MAX をチェックし、errno については ERANGE をチェックします。

#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<limits.h>

int main(int argc, char *argv[]) {
    char *str, *endptr;
    int base;
    
    str = argv[1];
    base = 10;
    
    errno = 0;
    long val = strtol(str, &endptr, base);
    if((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) {
         printf("strtol error");
         exit(EXIT_FAILURE);
    }        
    printf("Return value of strtol() = %ld\n", val);
}

結果情報

グループ: セキュリティ
言語: C | C++
既定値: オフ
コマンド ライン構文: ERRNO_NOT_CHECKED
影響度: Medium

バージョン履歴

R2017a で導入