メインコンテンツ

文字列から数値への変換は安全ではありません

検証チェックなしの文字列から数値への変換

説明

この欠陥は、文字列から整数または浮動小数点値への変換が行われ、その変換メソッドにロバストなエラー処理が含まれていなかった場合に発生します。

リスク

文字列を数値に変換すると、データの損失や誤った解釈の原因となる場合があります。変換の検証またはエラー処理がないと、プロクラムは無効な値を使って続行されます。

修正方法

  • 数値を検証する新たなチェックを追加します。

  • strtolstrtollstrtoulstrtoull などの、文字列から数値へのよりロバストな変換関数を使用します。

すべて展開する

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

static int demo_check_string_not_empty(char *s)
{
    if (s != NULL)
        return strlen(s) > 0; /* check string null-terminated and not empty */
    else
        return 0;
}

int unsafestrtonumeric(char* argv1)
{
    int s = 0;
    if (demo_check_string_not_empty(argv1))
    {
        s = atoi(argv1); 
    }
    return s;
}

この例では、atoi を使って argv1 を整数に変換しています。atoi では無効な整数の文字列についてのエラーが提供されません。この変換は予期せず失敗する可能性があります。

修正 — 代わりに strtol を使用

考えられる 1 つの修正方法として、strtol を使用して入力文字列と変換後の整数を検証します。

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

static int demo_check_string_not_empty(char *s)
{
    if (s != NULL)
        return strlen(s) > 0; /* check string null-terminated and not empty */
    else
        return 0;
}

int unsafestrtonumeric(char *argv1)
{
    char *c_str = argv1;
    char *end;
    long sl;

    if (demo_check_string_not_empty(c_str))
    {
        errno = 0; /* set errno for error check */
        sl = strtol(c_str, &end, 10);
        if (end == c_str)
        {
            (void)fprintf(stderr, "%s: not a decimal number\n", c_str);
        }
        else if ('\0' != *end)
        {
            (void)fprintf(stderr, "%s: extra characters: %s\n", c_str, end);
        }
        else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno)
        {
            (void)fprintf(stderr, "%s out of range of type long\n", c_str);
        }
        else if (sl > INT_MAX)
        {
            (void)fprintf(stderr, "%ld greater than INT_MAX\n", sl);
        }
        else if (sl < INT_MIN)
        {
            (void)fprintf(stderr, "%ld less than INT_MIN\n", sl);
        }
        else
        {
            return (int)sl;
        }
    }
    return 0;
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: オフ
コマンド ライン構文: UNSAFE_STR_TO_NUMERIC
影響度: Low

バージョン履歴

R2016b で導入