メインコンテンツ

汚染された符号変化の変換

セキュリティで保護されないソースに由来する値の符号の変化

説明

この欠陥は、セキュリティで保護されていないソースからの値が、符号付きの値から符号なしの値に暗黙的または明示的に変換された場合に発生します。

たとえば、size_t を引数として使用する関数では、引数が暗黙的に符号なし整数に変換されます。size_t を暗黙的に変換する関数のいくつかを、以下に挙げます。

bcmp
memcpy
memmove
strncmp
strncpy
calloc
malloc
memalign

リスク

小さい負の数値を符号なしに変換すると、その結果は大きい正の数値となります。大きい正の数値により、セキュリティが脆弱になる可能性があります。たとえば、符号なしの値を以下で使用した場合がこれに該当します。

  • メモリ サイズ ルーチン — メモリ割り当ての問題の原因となります。

  • 文字列操作ルーチン — バッファー オーバーフローの原因となります。

  • ループ境界 — 無限ループの原因となります。

修正方法

符号なしの負の値の変換を避けるため、変換対象の値が許容範囲内にあることを確認します。たとえば、値がサイズを表す場合は、その値が負ではなく値の最大サイズより小さいことを検証します。

チェッカーの拡張

既定では、Polyspace® は外部ソースからのデータは汚染されていると仮定します。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary] を使用します。

すべて展開する

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

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void bug_taintedsignchange(void) {
    int size;
    scanf("%d",&size);
    char str[SIZE128] = "";
    if (size<SIZE128) {
        memset(str, 'c', size); //Noncompliant
    }
}

この例では、バッファー char が作成され、memset を使用して埋められます。memset のサイズ引数は、関数の入力引数です。

memset を呼び出すことにより、size が符号なし整数へと暗黙的に変換されます。size が大きい負の数値である場合、その絶対値は整数で表現するには大きすぎる可能性があり、バッファー オーバーフローの原因となります。

修正 — size の値をチェック

1 つの修正方法として、size が有効範囲内にあるかどうかをチェックします。この修正では、size がゼロより大きくバッファー サイズより小さいかどうかを、memset を呼び出す前にチェックします。

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

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void corrected_taintedsignchange(void) {
    int size;
    scanf("%d",&size);
    char str[SIZE128] = "";
    if (size>0 && size<SIZE128) {
        memset(str, 'c', size);  
    }
}

結果情報

グループ: 汚染されたデータ
言語: C | C++
既定値: オフ
コマンド ライン構文: TAINTED_SIGN_CHANGE
影響度: Medium

バージョン履歴

R2015b で導入