メインコンテンツ

負値でのビット演算です

負値でのビット演算による未定義の動作

説明

この欠陥は、ビット演算子 (>>^|~butnot&) が、値が負の符号付き整数変数に使用された場合に発生します。

リスク

符号付き整数の値が負の場合、ビット演算は以下の理由により予期しない結果になる可能性があります。

  • 負の値に対するビット演算では、コンパイラ固有の結果が生成される可能性があります。

  • 予期しない計算は、バッファー オーバーフローなど、さらなる脆弱性につながることがある。

修正方法

ビット演算を行う際に、unsigned 整数を使用して予期しない結果になるのを回避します。

チェッカーの拡張

入力値が不明であり、入力のサブセットのみがエラーの原因となっている場合、既定の Bug Finder 解析ではこの欠陥が報告されない可能性があります。特定のシステム入力値を原因とする欠陥の有無をチェックするには、より厳密な Bug Finder 解析を実行してください。特定のシステム入力値から欠陥を見つけるための Bug Finder チェッカーの拡張を参照してください。

すべて展開する

#include <stdio.h>
#include <stdarg.h>

static void demo_sprintf(const char *format, ...)
{
    int rc;
    va_list ap;
    char buf[sizeof("256")];

    va_start(ap, format);
    rc = vsprintf(buf, format, ap);
    if (rc == -1 || rc >= sizeof(buf)) {
        /* Handle error */
    }
    va_end(ap);
}

void bug_bitwiseneg()
{
    int stringify = 0x80000000;
    demo_sprintf("%u", stringify >> 24);
}

この例では、ステートメント demo_sprintf("%u", stringify >> 24) によりプログラムが予期せず停止します。stringify >> 24 の結果は 0x80 になると想定されます。しかし、stringify は符号付きで負の値になるため、実際の結果は 0xffffff80 となります。符号ビットもシフトされます。

修正 — キーワード unsigned を追加

キーワード unsigned を追加することで、stringify は負の値ではなくなり、右シフト演算により予想どおり 0x80 になります。

#include <stdio.h>
#include <stdarg.h>

static void demo_sprintf(const char *format, ...)
{
    int rc;
    va_list ap;
    char buf[sizeof("256")];

    va_start(ap, format);
    rc = vsprintf(buf, format, ap);
    if (rc == -1 || rc >= sizeof(buf)) {
        /* Handle error */
    }
    va_end(ap);
}

void corrected_bitwiseneg()
{
    unsigned int stringify = 0x80000000;
    demo_sprintf("%u", stringify >> 24);
}

結果情報

グループ: 数値
言語: C | C++
既定値: オフ
コマンド ライン構文: BITWISE_NEG
影響度: Medium

バージョン履歴

R2016b で導入