問題はここにあります:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
文字列がターゲットバッファーの長さより長い場合でも、strncpyはそれをコピーします。バッファのサイズではなく、文字列の文字数をコピーする数として使用しています。これを行う正しい方法は次のとおりです。
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
これにより、コピーされるデータの量は、バッファーの実際のサイズからnull終了文字の1を引いたものに制限されます。次に、追加の保護手段として、バッファーの最後のバイトをnull文字に設定します。この理由は、strlen(str)<len-1の場合、strncpyは終端のnullを含めてnバイトまでコピーするためです。そうでない場合、nullはコピーされず、バッファが終了していないためクラッシュシナリオが発生します。ストリング。
お役に立てれば。
編集:さらに調査し、他のユーザーから入力すると、関数の可能なコーディングは次のようになります。
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
文字列の長さがわかっているので、memcpyを使用して、strによって参照される場所から文字列をバッファにコピーできます。strlen(3)のマニュアルページ(FreeBSD 9.3システム上)では、次のように述べられています。
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
文字列の長さにnullが含まれていないと私は解釈します。そのため、len + 1バイトをコピーしてnullを含め、テストでは、長さ<バッファーのサイズ-2であることを確認します。バッファーが位置0から始まるため、マイナス1と、スペースがあることを確認するためにもう1つマイナスします。ヌル。
編集:結局のところ、何かのサイズは1で始まり、アクセスは0で始まるため、98バイトを超えるとエラーが返されるため、以前の-2は正しくありませんが、99バイトを超える必要があります。
編集:unsigned shortについての答えは、表現できる最大長が65,535文字であるため、通常は正しいですが、文字列がそれより長い場合、値が折り返されるため、実際には問題ではありません。これは、75,231(0x000125DF)を取得し、上位16ビットをマスクして9695(0x000025DF)を取得するようなものです。長さのチェックではコピーが許可されるため、これで私が見る唯一の問題は65,535を超える最初の100文字ですが、すべての場合に文字列の最初の100文字までしかコピーされず、文字列はnullで終了します。したがって、ラップアラウンドの問題があっても、バッファがオーバーフローすることはありません。
文字列の内容とそれを何に使用するかによって、これ自体がセキュリティリスクをもたらす場合とそうでない場合があります。人間が読めるのが単なるテキストの場合、通常は問題ありません。切り捨てられた文字列を取得するだけです。ただし、URLやSQLコマンドシーケンスなどの場合は、問題が発生する可能性があります。