5

次のCコードフラグメントがあり、エラーを特定して、より安全に記述する方法を提案する必要があります。

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strcpy(copy, somestring);
printf(copy);

したがって、エラーは、strlenが'\0'文字列の末尾を無視するため、コピーに十分なメモリが割り当てられないということですが、より安全に書き込むことで何が得られるのかわかりません。

私は私が想定しているものを使用することができますmalloc(strlen(somestring)+1))が、それよりも良い方法があるに違いないと思いますか?


編集: OK、私は答えを受け入れました、それはANSI Cの一部ではないので、strdupソリューションは私たちから期待されないだろうと思います。それはかなり主観的な質問のようですので、私が何をしたかわかりません受け入れられたのは実際には最高です。とにかくすべての答えをありがとう。

4

10 に答える 10

7

上記の応答についてコメントすることはできませんが、リターンコードを確認してを使用することに加えてstrncpy、次のことを行うべきではありません。

printf(string)

しかし、使用してください:

printf("%s", string);

参照: http: //en.wikipedia.org/wiki/Format_string_attack

于 2009-05-26T17:49:42.153 に答える
6
char somestring[] = "Send money!\n";
char *copy = strdup(something);

if (copy == NULL) {
    // error
}

または、このロジックを別の関数xstrdupに配置します。

char * xstrdup(const char *src) 
{
    char *copy = strdup(src);

    if (copy == NULL) {
       abort();
    }

    return copy;
}
于 2009-05-26T16:52:50.600 に答える
4
char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

strncpy(copy, somestring, copysize);
printf("%s", copy);

上記の違いに注意してください:

  • 結果をmalloc()確認する必要があります!
  • メモリサイズを計算して保存します。
  • やんちゃなstrncpy()ので使ってください。strcpy()この不自然な例では、それは害を及ぼすことはありませんが、それを使用する習慣を身につけないでください。

編集:

私が使うべきだと思っている人にはstrdup()...それはあなたが質問の非常に狭い見方をした場合にのみ機能します。それはばかげているだけでなく、さらに良い答えを見落としています。

char somestring[] = "Send money!\n";
char *copy = somestring;
printf(copy);

あなたが鈍感になるつもりなら、少なくともそれが得意です。

于 2009-05-26T17:01:37.103 に答える
3
  1. strlen + 1、\0ターミネーターの場合
  2. mallocが失敗する可能性があります。常にmallocの戻り値を確認してください
于 2009-05-26T16:59:50.647 に答える
3

Ick ...strdup()他のみんなが言ったように使用し、必要に応じて自分で書いてください。あなたは今これについて考える時間があるので...マイターで25の最も危険なプログラミングエラーをチェックして、そしてなぜそのフレーズがコードに決して現れてはprintf(copy)ならないのかを考えてください。それは、コピーが次のようなものであるときになぜそれが多くの悲しみを引き起こすのかを追跡するという頭痛の種は言うまでもなく、まったくの悪さの点ですぐそこにあります...malloc(strlen(str))"%s%n"

于 2009-05-26T17:43:20.733 に答える
1

以前の解決策にコメントしますが、十分な担当者がいません。ここでstrncpyを使用することは、 strcpyを使用することと同じくらい間違っています(オーバーフローのリスクがまったくないため)。<string.h>にはmemcpyという関数があり、これはまさにこのためのものです。これは大幅に高速であるだけでなく、標準Cで既知の長さの文字列をコピーするために使用する正しい関数でもあります。

受け入れられた答えから:

char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

memcpy(copy, somestring, copysize); /* You don't use str* functions for this! */
printf("%s", copy);
于 2009-05-27T01:56:46.617 に答える
1

より安全なコードを作成するためのエイドリアンマッカーシーの方法にさらに追加するには、

静的コードアナライザーを使用してください。この種のエラーを見つけるのに非常に優れています。

于 2009-05-28T04:02:22.213 に答える
1

コードをより安全に(そしてより正確に)する方法。

  1. 不要なコピーを作成しないでください。この例から、実際にコピーする必要があるという明らかな要件はありませんsomestring。直接出力できます。
  2. 文字列のコピーを作成する必要がある場合は、それを実行する関数を記述します(または、ある場合はstrdupを使用します)。そうすれば、1か所で正しく理解する必要があります。
  3. 可能な限り、宣言した直後にコピーへのポインタを初期化します。
  4. ヌルターミネータにスペースを割り当てることを忘れないでください。
  5. からの戻り値を確認することを忘れないでくださいmalloc
  6. malloc'edメモリを解放することを忘れないでください。
  7. printf信頼できないフォーマット文字列で呼び出さないでください。printf("%s", copy)またはを使用しputs(copy)ます。
  8. これらの問題のほとんどを回避するには、文字列クラスを備えたオブジェクト指向言語、または文字列サポートが組み込まれた任意の言語を使用してください。
于 2009-05-27T17:08:39.493 に答える
0

より安全に書くための最良の方法は、もしそのようなことに本当に興味があるなら、それをエイダで書くことでしょう。

somestring : constant string := "Send money!";
declare
   copy : constant string := somestring;
begin
   put_line (somestring);
end;

同じ結果ですが、違いは何ですか?

  • すべてがスタック上で行われます(ポインターなし)。割り当て解除は自動的で安全です。
  • すべてが自動的に範囲チェックされるため、バッファオーバーフローが悪用される可能性はありません。
  • 両方の文字列は定数であるため、それらを台無しにして変更する可能性はありません。
  • 動的な割り当てがないだけでなく、strlen()に必要な文字列を余分にスキャンする必要がないため、おそらくCよりもはるかに高速です。

Adaでは、「文字列」は特別な動的構造ではないことに注意してください。これは、組み込みの文字配列です。ただし、Ada配列は、割り当てた配列によって宣言時にサイズ変更できます。

于 2009-05-26T17:18:25.773 に答える
-2

より安全な方法は、strncpyの代わりに使用することですstrcpy。その関数は3番目の引数を取ります:コピーする文字列の長さ。このソリューションはANSICを超えて拡張されないため、これはすべての環境で機能します(他の方法は、POSIX準拠のシステムでのみ機能する可能性があります)。

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strncpy(copy, somestring, strlen(somestring));
printf(copy);
于 2009-05-26T16:52:58.947 に答える