メインコンテンツ

AUTOSAR C++14 Rule A27-0-2

A C-style string shall guarantee sufficient space for data and the null terminator

説明

ルール定義

A C-style string shall guarantee sufficient space for data and the null terminator.

根拠

C スタイルの文字列は書き込まれる文字データの容量に加え、末尾の null 終端のために明示的な 1 文字を必要とします。必要な容量に対応できないとバッファー オーバーフローが発生し、メモリの破損、セキュリティの脆弱性、その他の問題につながります。

Polyspace 実装

チェッカーは次の問題を検出します。

  • 危険な標準関数を使用している。

    この問題は、getsstrcpy などの C 関数を使用している場合に発生します。これはデータをバッファに書き込みますが、書き込まれるデータの長さに対する制御は本質的に提供しません。

    関数の完全なリストとその安全な代替方法については、危険な標準関数の使用を参照してください。

  • 不正確な文字列形式指定子によるバッファー オーバーフロー。

    この問題は、sscanf などの C 関数の書式指定子引数が、メモリ バッファー引数でのオーバーフローまたはアンダーフローにつながる場合に発生します。

  • 文字列操作で格納先バッファーがオーバーフローしています。

    この問題は、特定の C 文字列操作関数によって、その格納先バッファー引数にバッファー サイズを超えるオフセットで書き込まれた場合に発生します。

    たとえば、関数 sprintf(char* buffer, const char* format) を呼び出す際に、buffer より大きいサイズの定数文字列 format を使用する場合などです。

  • 格納先バッファー サイズが不十分

    この現象は、strcpy 演算内の格納先バッファーにソース バッファーと null 終端が収まらない場合に発生します。この問題は、ソース バッファーのサイズが不明な場合に報告されます。

トラブルシューティング

ルール違反が想定されるものの、Polyspace® から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include <cstdio>
#include <cstring>

#define BUFF_SIZE 128


int noncompliant_func(char *str) {
    char dst[BUFF_SIZE];
    int r = 0;

    if (sprintf(dst, "%s", str) == 1) { //Noncompliant
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

int compliant_func(char *str) {
    char dst[BUFF_SIZE];
    int r = 0;

    if (snprintf(dst, sizeof(dst), "%s", str) == 1) { //Compliant
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

この例では、sprintf 関数を使用しているときにルールに違反します。これは、書き込まれるデータの長さを制御できません。潜在的なバッファー オーバーフローを避けるには、より安全な代替関数 snprintf を使用します。

#include <cstdio>

void noncompliant_func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%33c", buf); //Noncompliant
}

void compliant_func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%32c", buf); //Compliant
}

この例では、バッファー bufchar 要素を 32 個格納できます。したがって、書式指定子 %33c はバッファー オーバーフローの原因となり、ルールに違反します。ルール違反を避けるには、より少ない数の要素をバッファーに読み取ります。

#include <cstdio>

void noncompliant_func(void) {
    char buf[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    sprintf(buf, fmt_string); //Noncompliant
}

void compliant_func(void) {
    char buf[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    snprintf(buf, 20, fmt_string); //Compliant
}

この例では、bufchar 要素を 20 個格納できます。したがって、これより大きいサイズの fmt_string はバッファー オーバーフローの原因となり、ルールに違反します。ルール違反を避けるには、snprintf を使用して長さの制御を行い、20 より少ない数の要素をバッファーに読み取ります。

この例では、source バッファーのサイズは不明ですが、destination バッファーのサイズは 128 で固定されます。この destination バッファーのサイズは、source バッファーからの文字を収め、そのバッファーを null で終了するには不十分な可能性があります。Polyspace は、ルールの違反を報告します。

#include <string.h>
  
int main(int argc, char *argv[]) {
  const char *const source = (argc && argv[0]) ? argv[0] : "";
  char destination[128];
  strcpy(const_cast<char*>(source), destination);//Noncompliant
  
  return 0;
}
修正 — 格納先として十分なメモリを割り当てる

この違反は、destination バッファーに十分なメモリを割り当てることによって解決されます。たとえば、関数 strlen() を使用して source バッファーのサイズを計算し、source バッファーからのすべての文字と null 終端 ('\0') を収めるのに十分なメモリを destination バッファーに割り当てます。

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

int main(int argc, char *argv[]) {
  const char *const source = (argc && argv[0]) ? argv[0] : "";
  char* destination = (char *)malloc(strlen(source)+ 1);
  if(destination!=NULL){
      strcpy(const_cast<char*>(source), destination);//Compliant
  }else{
      /*Handle Error*/
  }
  //...
  free(destination);
  return 0;
}

チェック情報

グループ: Input/output library
カテゴリ: Advisory、Automated

バージョン履歴

R2020b で導入

すべて展開する