メインコンテンツ

ISO/IEC TS 17961 [taintstrcpy]

Tainted strings are passed to a string copying function

説明

文字列コピー関数に汚染された文字列を渡す。1

Polyspace 実装

このチェッカーは、汚染された NULL 文字列または非 NULL 終端文字列をチェックします。

チェッカーの拡張

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

すべて展開する

問題

汚染された NULL 文字列または非 NULL 終端文字列は、文字列バッファーを暗黙的にデリファレンスする文字列操作ルーチンで使用される、セキュリティで保護されないソースに由来する文字列を調べます。たとえば、strcpysprintf などがこれに該当します。

汚染された NULL 文字列または非 NULL 終端文字列では、scanf ファミリの可変個引数関数の呼び出しから返された文字列に関する欠陥が報告されません。同様に、文字列と一緒に %s 指定子を printf ファミリの可変個引数関数に渡した場合も欠陥は報告されません。

メモ

文字列が形式 ptr[i]*ptr またはポインター演算を使用して参照される場合は、Bug Finder によって、代わりに汚染されたポインターの使用の欠陥が報告されます。汚染された NULL 文字列または非 NULL 終端文字列の欠陥は、ポインターが文字列として使用される場合にのみ報告されます。

リスク

文字列がセキュリティで保護されないソースに由来している場合、攻撃者により文字列が操作されている可能性や、文字列ポインターが異なるメモリ位置に向けられている可能性があります。

文字列が NULL である場合、文字列ルーチンは文字列をデリファレンスできず、プログラムがクラッシュする原因となります。文字列が null で終了しない場合、文字列ルーチンでは文字列がいつ終了するかわからない可能性があります。このエラーは範囲外への書き込みの原因となり、バッファー オーバーフローを引き起こします。

修正方法

文字列は、使用する前に検証します。以下についてチェックします。

  • 文字列が NULL でない。

  • 文字列が null で終了している。

  • 文字列のサイズが、必要なサイズと一致している。

例 - 文字列を入力引数から取得
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define SIZE128 128
#define MAX 40

extern void print_str(const char*);

void warningMsg(void)
{
    char userstr[MAX];
    read(0, userstr, MAX);
    char str[SIZE128] = "Warning: ";
    strncat(str, userstr, SIZE128 - (strlen(str) + 1));//Noncompliant
    print_str(str);
}

この例では、文字列 str は引数 userstr と連結しています。userstr の値は不明です。userstr のサイズが使用可能なスペースより大きい場合、この連結はオーバーフローします。

修正 — データを検証

1 つの修正方法として、strncat で使用する前に、userstr のサイズをチェックして、文字列が必ず null で終了するようにします。この例では、補助関数 sanitize_str を使用して文字列を検証しています。補助関数を使用すると、欠陥をその関数に集中させることができます。

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

#define SIZE128 128
#define MAX 40

extern void print_str(const char*);

int sanitize_str(char* s) 
{
    int res = 0; 
    if (s && (strlen(s) > 0)) { //Noncompliant
        res = 1;
    }
    return res; 
}

void warningMsg(void)
{
    char userstr[MAX];
    read(0, userstr, MAX);
    char str[SIZE128] = "Warning: ";
    if (sanitize_str(userstr))	
        strncat(str, userstr, SIZE128 - (strlen(str) + 1));
    print_str(str);
}
修正 — データを検証

別の修正方法として、特定の文字列を含む関数 errorMsg および warningMsg を呼び出します。

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

#define SIZE128 128

extern void print_str(const char*);

void warningMsg(char* userstr)
{
    char str[SIZE128] = "Warning: ";
    strncat(str, userstr, SIZE128 - (strlen(str) + 1));
    print_str(str);
}

void errorMsg(char* userstr)
{
    char str[SIZE128] = "Error: ";
    strncat(str, userstr, SIZE128 - (strlen(str) + 1));
    print_str(str);
}

int manageSensorValue(int sensorValue) 
{
    int ret = sensorValue;
    if (sensorValue < 0) {
        errorMsg("sensor value should be positive");
        exit(1);
    } else if (sensorValue > 50) {
        warningMsg("sensor value greater than 50 (applying threshold)...");
        sensorValue = 50;
    }
    return sensorValue;
}

チェック情報

決定可能性:決定不可能

バージョン履歴

R2019a で導入


1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.