63

asprintf が必要な理由を理解するのに苦労しています。ここのマニュアルにはこう書かれています

関数asprintf()とはと vasprintf()の類似物ですが、終端の null バイトを含む出力を保持するのに十分な大きさの文字列を割り当て、最初の引数を介してその文字列へのポインタを返します。割り当てられたストレージが不要になったときに解放するには、このポインタを に渡す 必要があります。sprintf(3)vsprintf(3)free(3)

だからここに私が理解しようとしている例があります:

asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));

バッファが十分な大きさの文字列を割り当てる場合と、char* = (string) と言う場合の違いは何ですか

4

2 に答える 2

134

sprintf()またはを使用する場合はvsprintf()、最初にバッファーを割り当てる必要があります。また、バッファーがsprintfの書き込みを含むのに十分な大きさであることを確認する必要があります。それ以外の場合sprintf()は、バッファの終わりを超えて存在するすべてのメモリを喜んで上書きします。

char* x = malloc(5 * sizeof(char));
// writes "123456" +null but overruns the buffer
sprintf(x,"%s%s%s", "12", "34", "56");

null...に割り当てられたスペースの終わりを超えて「6」と終了を書き込み、x他の変数を破損するか、セグメンテーション違反を引き起こします。

運が良ければ、割り当てられたブロックの間のメモリを踏みにじり、害を及ぼすことはありません-今回は。これは断続的なバグにつながります-診断するのが最も難しい種類です。オーバーランをフェイルファストで発生させるElectricFenceのようなツールを使用することをお勧めします。

過度に長い入力を提供する悪意のないユーザーは、プログラムが予期しない方法で動作する原因となる可能性があります。悪意のあるユーザーは、自分の実行可能コードをシステムに取り込む方法としてこれを悪用する可能性があります。

これに対する1つの予防策は、を使用することです。これはsnprintf()、指定した最大長に文字列を切り捨てます。

char *x = malloc(5 * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); // writes "1234" + null

戻り値は、スペースが使用可能であった場合size書き込まれる長さであり、終了nullは含まれません

この場合、sizeが5以上であれば、切り捨てが発生したことがわかります。切り捨てたくない場合は、新しい文字列を割り当てて再試行できますsnprintf()

char *x = malloc(BUF_LEN * sizeof(char));
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56");
if (size >= BUF_LEN) {
    realloc(&x,(size + 1) * sizeof(char));
    snprintf(x, size + 1 , "%s%s%s", "12", "34", "56");
}

(これはかなり単純なアルゴリズムですが、要点を示しています。まだバグが含まれている可能性があります。これにより、要点がさらにわかります。これは簡単に失敗します。)

asprintf()これを1つのステップで実行します-文字列の長さを計算し、その量のメモリを割り当てて、文字列を書き込みます。

char *x;
int size = asprintf(&x, "%s%s%s", "12", "34", "56");

いずれの場合も、終了しxたら解放する必要があります。そうしないと、メモリがリークします。

free(x);

asprintf()は暗黙的であるため、他のシステムコールmalloc()と同じように、機能することを確認する必要があります。malloc()

if (size == -1 ) {
   /* deal with error in some way */
}

これはlibcのGNUおよびBSD拡張機能の一部であることに注意してくださいasprintf()。すべてのC環境で使用できるかどうかはわかりません。sprintf()およびsnprintf()はPOSIXおよびC99標準の一部です。

于 2012-10-05T13:19:09.613 に答える
21

利点はセキュリティです。

多数のプログラムにより、ユーザーが提供するデータでいっぱいになったときにプログラマーが提供するバッファーがオーバーフローすることにより、システムの悪用が発生する可能性があります。

バッファをasprintf割り当てることで、それが起こらないことが保証されます。

ただし、の戻り値をチェックして、メモリ割り当てが実際に成功したことを確認する必要があります。http://blogs.23.nu/ilja/2006/10/antville-12995/asprintfを参照してください

于 2012-10-05T13:09:12.113 に答える