メインコンテンツ

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

CERT C: Rule ARR32-C

Ensure size arguments for variable length arrays are in a valid range

説明

ルール定義

可変長配列のサイズ引数が有効な範囲内になるようにします。1

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • 汚染されたサイズでのメモリの割り当て

  • 可変長配列の汚染されたサイズ

チェッカーの拡張

既定の Bug Finder 解析では、現在の解析境界の外部からの特定の入力に関する "汚染されたサイズでのメモリの割り当て""可変長配列の汚染されたサイズ" 問題にフラグを設定しない場合があります。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary] を使用します。

すべて展開する

問題

汚染されたサイズでのメモリの割り当てでは、callocmalloc のようなメモリ割り当て関数を、セキュリティで保護されないソース由来のサイズ引数についてチェックします。

リスク

メモリ割り当てが制御されていないと、プログラムによってシステム メモリが過剰に要求されることがあります。その結果、メモリ不足の状態やリソースの過剰割り当てによりクラッシュすることがあります。

修正方法

メモリを割り当てる前に引数の値をチェックして、範囲を超えないことを確認します。

例 - 入力引数を使用したメモリの割り当て
#include<stdio.h>
#include <stdlib.h>

int* bug_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = (int*)malloc(size); //Noncompliant
    return p;
}

この例では、malloc がポインター psize 量のメモリを割り当てます。size は外部の変数であるため、サイズの値は任意となります。サイズが使用可能なメモリの量よりも大きい場合、プログラムはクラッシュする可能性があります。

修正 — 割り当てられるメモリのサイズをチェック

1 つの修正方法として、malloc 操作を実行する前に、割り当てるメモリのサイズをチェックします。この例では、サイズが正であり最大サイズより小さいことを確認するためにチェックしています。

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

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

int* corrected_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = NULL;
    if (size>0 && size<SIZE128) {          /* Fix: Check entry range before use */
        p = (int*)malloc((unsigned int)size);
    }
    return p;
}
問題

可変長配列の汚染されたサイズでは、セキュリティで保護されないソースに由来するサイズの可変長配列 (VLA) を検出します。

リスク

攻撃者が VLA のサイズを予期しない値に変更した場合、プログラムのクラッシュや予期しない動作の原因となることがあります。

サイズが正でない場合、VLA の動作は未定義となります。プログラムは想定どおりには実行されません。

サイズが無制限の場合、VLA はメモリ枯渇やスタック オーバーフローを引き起こすことがあります。

修正方法

VLA のサイズを検証して、正であり最大値より小さいことを確認します。

例 - VLA のサイズとして使用される入力引数
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size]; //Noncompliant
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

この例では、可変長配列のサイズが入力引数に基づいています。この入力引数の値はチェックされていないため、サイズが負になるか大きすぎる可能性があります。

修正 — VLA のサイズをチェック

1 つの修正方法として、可変長配列を作成する前にサイズ変数をチェックします。この例では、VLA を作成する前に、サイズが 10 より大きく 100 より小さいかどうかをチェックしています。

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

チェック情報

グループ: Rule 06.配列 (ARR)

バージョン履歴

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.