std :: stringは通常、バッファオーバーフローから保護しますが、プログラミングエラーがバッファオーバーフローにつながる可能性がある状況もあります。C ++は通常、操作が文字列の境界外のメモリを参照するときにout_of_range例外をスローしますが、添え字演算子[](境界チェックを実行しない)はスローしません。
std::stringオブジェクトをCスタイルの文字列に変換するときに別の問題が発生します。string :: c_str()を使用して変換を行うと、適切にnullで終了するCスタイルの文字列が得られます。ただし、文字列を配列に直接書き込む(配列へのポインタを返す)string :: data()を使用すると、nullで終了しないバッファが得られます。The only difference between c_str() and data() is that c_str() adds a trailing null byte.
最後に、多くの既存のC++プログラムとライブラリには独自の文字列クラスがあります。これらのライブラリを使用するには、これらの文字列タイプを使用するか、常に前後に変換する必要がある場合があります。このようなライブラリは、セキュリティに関してはさまざまな品質のものです。一般に、標準ライブラリを使用するか(可能な場合)、選択したライブラリのセマンティクスを理解するのが最善です。一般的に、ライブラリは、使用のしやすさや複雑さ、発生する可能性のあるエラーの種類、これらのエラーの発生のしやすさ、および潜在的な結果に基づいて評価する必要があります。https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/295-BSI.htmlを参照してください
cでは、原因は次のように説明されています。
void function (char *str) {
char buffer[16];
strcpy (buffer, str);
}
int main () {
char *str = "I am greater than 16 bytes"; // length of str = 27 bytes
function (str);
}
このプログラムは、27バイトの文字列(str)が16バイトのみに割り当てられた場所(バッファ)にコピーされているため、予期しない動作を引き起こすことが保証されています。余分なバイトはバッファを通過し、FP、リターンアドレスなどに割り当てられたスペースを上書きします。これにより、プロセススタックが破損します。文字列のコピーに使用される関数はstrcpyであり、境界のチェックを完了しません。strncpyを使用すると、このスタックの破損を防ぐことができます。ただし、この古典的な例は、バッファオーバーフローによって関数のリターンアドレスが上書きされ、プログラムの実行パスが変更される可能性があることを示しています。関数のリターンアドレスは、関数が戻った直後に実行されるメモリ内の次の命令のアドレスであることを思い出してください。
ここにあなたの答えを満足させることができる良いチュートリアルがあります。