私はこのようにします:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define HUGE_BUFFER_SIZE 4096
int main (int argc, char **argv) {
static char buf[HUGE_BUFFER_SIZE + 1];
char servername[200];
int target_len, servername_len, buf_len = 0;
char *out = NULL;
strcpy(buf, "this is my test buffer!");
strcpy(servername, "127.0.0.1");
/* Notice the uses of strnlen. Each of these fixes the maximum number of characters that will be scanned. */
servername_len = strnlen(servername, HUGE_BUFFER_SIZE+1) + 1;
buf_len = strnlen(buf, 200) + 4;
target_len = servername_len, buf_len;
if ((out = alloca(target_len)) == NULL)
return EXIT_FAILURE; /* alloc failed, die quickly! */
/* At this point, you've measured the length of servername and buf using strlen, so it should really be impossible to run beyond the length of your buffer, but we're going to be careful, anyway */
out[0] = '\0';
strncat(out, servername, servername_len);
strncat(out, buf, buf_len);
printf("%s\n", out);
return EXIT_SUCCESS;
}
(コピー/貼り付けエラー、またはシステム上のさまざまなライブラリと私の側のクロスプラットフォームの混乱を除けば、これをファイルに貼り付け、コンパイルして実行できるはずです。「127.0.0.1thisis私のテストバッファ!」を出力として)
strcpy、strcat、strncpy、strlcpyのいずれの場合でも、すべてのstr関数は、作成する文字列の末尾にnullターミネータをドロップすることに注意してください。手動でnullターミネータを設定する必要があるのは、「out [0] ='\ 0'」というステートメントで行ったように、まったく新しい文字列を開始するときだけです。
また、strlcatではなくstrnlenとstrncatを使用したことに注意してください。関数が何を返すかを除いて、strlcatとstrncatの違いはドキュメントからわかりません。
とにかく、バッファオーバーランのセキュリティホールがすべての関数呼び出しを明確に制限することを回避できるはずです。strncpyとstrncatは、コピーするデータの量を制限します。strnlenは、システムが「\0」を検索する期間を制限します。
編集:私の元のソリューションには、valgrindが明らかにしたエラーが実際にありました。私はbufもservernameも初期化していませんでした。他の何かが魔法のようにbufを初期化しているように見えましたが、valgrindは、サーバー名をターゲットとしてstrcatを呼び出すと、初期化されていないデータに基づいて決定が下されると報告しました。 doh。
変数を文字列リテラルで初期化するためにstrcatを呼び出した理由がわからないため、strcpyに切り替えました。もちろん、変数にコピーしている文字列を正確にアプリケーションにハードコーディングしているので、ここでは完全に安全です。